1 // RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
2 
3 class S {
4   int a;
5   S() : a(0) {}
6 
7 public:
8   S(int v) : a(v) {}
9   S(const S &s) : a(s.a) {}
10 };
11 
12 static int sii;
13 // expected-note@+1 {{defined as threadprivate or thread local}}
14 #pragma omp threadprivate(sii)
15 static int globalii;
16 
17 int test_iteration_spaces() {
18   const int N = 100;
19   float a[N], b[N], c[N];
20   int ii, jj, kk;
21   float fii;
22   double dii;
23 #pragma omp target
24 #pragma omp teams
25 #pragma omp distribute parallel for simd
26   for (int i = 0; i < 10; i += 1) {
27     c[i] = a[i] + b[i];
28   }
29 #pragma omp target
30 #pragma omp teams
31 #pragma omp distribute parallel for simd
32   for (char i = 0; i < 10; i++) {
33     c[i] = a[i] + b[i];
34   }
35 #pragma omp target
36 #pragma omp teams
37 #pragma omp distribute parallel for simd
38   for (char i = 0; i < 10; i += '\1') {
39     c[i] = a[i] + b[i];
40   }
41 #pragma omp target
42 #pragma omp teams
43 #pragma omp distribute parallel for simd
44   for (long long i = 0; i < 10; i++) {
45     c[i] = a[i] + b[i];
46   }
47 #pragma omp target
48 #pragma omp teams
49 // expected-error@+2 {{expression must have integral or unscoped enumeration type, not 'double'}}
50 #pragma omp distribute parallel for simd
51   for (long long i = 0; i < 10; i += 1.5) {
52     c[i] = a[i] + b[i];
53   }
54 #pragma omp target
55 #pragma omp teams
56 #pragma omp distribute parallel for simd
57   for (long long i = 0; i < 'z'; i += 1u) {
58     c[i] = a[i] + b[i];
59   }
60 #pragma omp target
61 #pragma omp teams
62 // expected-error@+2 {{variable must be of integer or random access iterator type}}
63 #pragma omp distribute parallel for simd
64   for (float fi = 0; fi < 10.0; fi++) {
65     c[(int)fi] = a[(int)fi] + b[(int)fi];
66   }
67 #pragma omp target
68 #pragma omp teams
69 // expected-error@+2 {{variable must be of integer or random access iterator type}}
70 #pragma omp distribute parallel for simd
71   for (double fi = 0; fi < 10.0; fi++) {
72     c[(int)fi] = a[(int)fi] + b[(int)fi];
73   }
74 #pragma omp target
75 #pragma omp teams
76 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
77 #pragma omp distribute parallel for simd
78   for (int &ref = ii; ref < 10; ref++) {
79   }
80 #pragma omp target
81 #pragma omp teams
82 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
83 #pragma omp distribute parallel for simd
84   for (int i; i < 10; i++)
85     c[i] = a[i];
86 
87 #pragma omp target
88 #pragma omp teams
89 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
90 #pragma omp distribute parallel for simd
91   for (int i = 0, j = 0; i < 10; ++i)
92     c[i] = a[i];
93 
94 #pragma omp target
95 #pragma omp teams
96 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
97 #pragma omp distribute parallel for simd
98   for (; ii < 10; ++ii)
99     c[ii] = a[ii];
100 
101 #pragma omp target
102 #pragma omp teams
103 // expected-warning@+3 {{expression result unused}}
104 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
105 #pragma omp distribute parallel for simd
106   for (ii + 1; ii < 10; ++ii)
107     c[ii] = a[ii];
108 
109 #pragma omp target
110 #pragma omp teams
111 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
112 #pragma omp distribute parallel for simd
113   for (c[ii] = 0; ii < 10; ++ii)
114     c[ii] = a[ii];
115 
116 #pragma omp target
117 #pragma omp teams
118 // Ok to skip parenthesises.
119 #pragma omp distribute parallel for simd
120   for (((ii)) = 0; ii < 10; ++ii)
121     c[ii] = a[ii];
122 
123 #pragma omp target
124 #pragma omp teams
125 // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
126 #pragma omp distribute parallel for simd
127   for (int i = 0; i; i++)
128     c[i] = a[i];
129 
130 #pragma omp target
131 #pragma omp teams
132 // expected-error@+3 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
133 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
134 #pragma omp distribute parallel for simd
135   for (int i = 0; jj < kk; ii++)
136     c[i] = a[i];
137 
138 #pragma omp target
139 #pragma omp teams
140 // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
141 #pragma omp distribute parallel for simd
142   for (int i = 0; !!i; i++)
143     c[i] = a[i];
144 
145 #pragma omp target
146 #pragma omp teams
147 // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
148 #pragma omp distribute parallel for simd
149   for (int i = 0; i != 1; i++)
150     c[i] = a[i];
151 
152 #pragma omp target
153 #pragma omp teams
154 // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
155 #pragma omp distribute parallel for simd
156   for (int i = 0;; i++)
157     c[i] = a[i];
158 
159 // Ok.
160 #pragma omp target
161 #pragma omp teams
162 #pragma omp distribute parallel for simd
163   for (int i = 11; i > 10; i--)
164     c[i] = a[i];
165 
166 // Ok.
167 #pragma omp target
168 #pragma omp teams
169 #pragma omp distribute parallel for simd
170   for (int i = 0; i < 10; ++i)
171     c[i] = a[i];
172 
173 // Ok.
174 #pragma omp target
175 #pragma omp teams
176 #pragma omp distribute parallel for simd
177   for (ii = 0; ii < 10; ++ii)
178     c[ii] = a[ii];
179 
180 #pragma omp target
181 #pragma omp teams
182 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
183 #pragma omp distribute parallel for simd
184   for (ii = 0; ii < 10; ++jj)
185     c[ii] = a[jj];
186 
187 #pragma omp target
188 #pragma omp teams
189 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
190 #pragma omp distribute parallel for simd
191   for (ii = 0; ii < 10; ++++ii)
192     c[ii] = a[ii];
193 
194 // Ok but undefined behavior (in general, cannot check that incr
195 // is really loop-invariant).
196 #pragma omp target
197 #pragma omp teams
198 #pragma omp distribute parallel for simd
199   for (ii = 0; ii < 10; ii = ii + ii)
200     c[ii] = a[ii];
201 
202 #pragma omp target
203 #pragma omp teams
204 // expected-error@+2 {{expression must have integral or unscoped enumeration type, not 'float'}}
205 #pragma omp distribute parallel for simd
206   for (ii = 0; ii < 10; ii = ii + 1.0f)
207     c[ii] = a[ii];
208 
209 // Ok - step was converted to integer type.
210 #pragma omp target
211 #pragma omp teams
212 #pragma omp distribute parallel for simd
213   for (ii = 0; ii < 10; ii = ii + (int)1.1f)
214     c[ii] = a[ii];
215 
216 #pragma omp target
217 #pragma omp teams
218 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
219 #pragma omp distribute parallel for simd
220   for (ii = 0; ii < 10; jj = ii + 2)
221     c[ii] = a[ii];
222 
223 #pragma omp target
224 #pragma omp teams
225 // expected-warning@+3 {{relational comparison result unused}}
226 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
227 #pragma omp distribute parallel for simd
228   for (ii = 0; ii<10; jj> kk + 2)
229     c[ii] = a[ii];
230 
231 #pragma omp target
232 #pragma omp teams
233 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
234 #pragma omp distribute parallel for simd
235   for (ii = 0; ii < 10;)
236     c[ii] = a[ii];
237 
238 #pragma omp target
239 #pragma omp teams
240 // expected-warning@+3 {{expression result unused}}
241 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
242 #pragma omp distribute parallel for simd
243   for (ii = 0; ii < 10; !ii)
244     c[ii] = a[ii];
245 
246 #pragma omp target
247 #pragma omp teams
248 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
249 #pragma omp distribute parallel for simd
250   for (ii = 0; ii < 10; ii ? ++ii : ++jj)
251     c[ii] = a[ii];
252 
253 #pragma omp target
254 #pragma omp teams
255 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
256 #pragma omp distribute parallel for simd
257   for (ii = 0; ii < 10; ii = ii < 10)
258     c[ii] = a[ii];
259 
260 #pragma omp target
261 #pragma omp teams
262 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
263 // expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
264 #pragma omp distribute parallel for simd
265   for (ii = 0; ii < 10; ii = ii + 0)
266     c[ii] = a[ii];
267 
268 #pragma omp target
269 #pragma omp teams
270 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
271 // expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
272 #pragma omp distribute parallel for simd
273   for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
274     c[ii] = a[ii];
275 
276 #pragma omp target
277 #pragma omp teams
278 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
279 // expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
280 #pragma omp distribute parallel for simd
281   for (ii = 0; (ii) < 10; ii -= 25)
282     c[ii] = a[ii];
283 
284 #pragma omp target
285 #pragma omp teams
286 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
287 // expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
288 #pragma omp distribute parallel for simd
289   for (ii = 0; (ii < 10); ii -= 0)
290     c[ii] = a[ii];
291 
292 #pragma omp target
293 #pragma omp teams
294 // expected-note@+3 {{loop step is expected to be negative due to this condition}}
295 // expected-error@+2 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
296 #pragma omp distribute parallel for simd
297   for (ii = 0; ii > 10; (ii += 0))
298     c[ii] = a[ii];
299 
300 #pragma omp target
301 #pragma omp teams
302 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
303 // expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
304 #pragma omp distribute parallel for simd
305   for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
306     c[ii] = a[ii];
307 
308 #pragma omp target
309 #pragma omp teams
310 // expected-note@+3 {{loop step is expected to be negative due to this condition}}
311 // expected-error@+2 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
312 #pragma omp distribute parallel for simd
313   for ((ii = 0); ii > 10; (ii -= 0))
314     c[ii] = a[ii];
315 
316 #pragma omp target
317 #pragma omp teams
318 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
319 // expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
320 #pragma omp distribute parallel for simd
321   for (ii = 0; (ii < 10); (ii -= 0))
322     c[ii] = a[ii];
323 
324 #pragma omp target
325 #pragma omp teams
326 // expected-note@+2  {{defined as firstprivate}}
327 // expected-error@+2 {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be firstprivate, predetermined as linear}}
328 #pragma omp distribute parallel for simd firstprivate(ii)
329   for (ii = 0; ii < 10; ii++)
330     c[ii] = a[ii];
331 
332 #pragma omp target
333 #pragma omp teams
334 #pragma omp distribute parallel for simd linear(ii)
335   for (ii = 0; ii < 10; ii++)
336     c[ii] = a[ii];
337 
338 #pragma omp target
339 #pragma omp teams
340 // expected-note@+2 {{defined as private}}
341 // expected-error@+2 {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be private, predetermined as linear}}
342 #pragma omp distribute parallel for simd private(ii)
343   for (ii = 0; ii < 10; ii++)
344     c[ii] = a[ii];
345 
346 #pragma omp target
347 #pragma omp teams
348 // expected-note@+2 {{defined as lastprivate}}
349 // expected-error@+2 {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be lastprivate, predetermined as linear}}
350 #pragma omp distribute parallel for simd lastprivate(ii)
351   for (ii = 0; ii < 10; ii++)
352     c[ii] = a[ii];
353 
354   {
355 // expected-error@+2 {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be threadprivate or thread local, predetermined as linear}}
356 #pragma omp distribute parallel for simd
357     for (sii = 0; sii < 10; sii += 1)
358       c[sii] = a[sii];
359   }
360 
361   {
362 #pragma omp distribute parallel for simd
363     for (globalii = 0; globalii < 10; globalii += 1)
364       c[globalii] = a[globalii];
365   }
366 
367   {
368 #pragma omp target
369 #pragma omp teams
370 #pragma omp distribute parallel for simd collapse(2)
371     for (ii = 0; ii < 10; ii += 1)
372     for (globalii = 0; globalii < 10; globalii += 1)
373       c[globalii] += a[globalii] + ii;
374   }
375 
376 #pragma omp target
377 #pragma omp teams
378 // expected-error@+2 {{statement after '#pragma omp distribute parallel for simd' must be a for loop}}
379 #pragma omp distribute parallel for simd
380   for (auto &item : a) {
381     item = item + 1;
382   }
383 
384 #pragma omp target
385 #pragma omp teams
386 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
387 // expected-error@+2 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
388 #pragma omp distribute parallel for simd
389   for (unsigned i = 9; i < 10; i--) {
390     c[i] = a[i] + b[i];
391   }
392 
393   int(*lb)[4] = nullptr;
394 #pragma omp target
395 #pragma omp teams
396 #pragma omp distribute parallel for simd
397   for (int(*p)[4] = lb; p < lb + 8; ++p) {
398   }
399 
400 #pragma omp target
401 #pragma omp teams
402 // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
403 #pragma omp distribute parallel for simd
404   for (int a{0}; a < 10; ++a) {
405   }
406 
407   return 0;
408 }
409 
410 // Iterators allowed in openmp for-loops.
411 namespace std {
412 struct random_access_iterator_tag {};
413 template <class Iter>
414 struct iterator_traits {
415   typedef typename Iter::difference_type difference_type;
416   typedef typename Iter::iterator_category iterator_category;
417 };
418 template <class Iter>
419 typename iterator_traits<Iter>::difference_type
420 distance(Iter first, Iter last) { return first - last; }
421 }
422 class Iter0 {
423 public:
424   Iter0() {}
425   Iter0(const Iter0 &) {}
426   Iter0 operator++() { return *this; }
427   Iter0 operator--() { return *this; }
428   bool operator<(Iter0 a) { return true; }
429 };
430 // expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
431 // expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
432 int operator-(Iter0 a, Iter0 b) { return 0; }
433 class Iter1 {
434 public:
435   Iter1(float f = 0.0f, double d = 0.0) {}
436   Iter1(const Iter1 &) {}
437   Iter1 operator++() { return *this; }
438   Iter1 operator--() { return *this; }
439   bool operator<(Iter1 a) { return true; }
440   bool operator>=(Iter1 a) { return false; }
441 };
442 class GoodIter {
443 public:
444   GoodIter() {}
445   GoodIter(const GoodIter &) {}
446   GoodIter(int fst, int snd) {}
447   GoodIter &operator=(const GoodIter &that) { return *this; }
448   GoodIter &operator=(const Iter0 &that) { return *this; }
449   GoodIter &operator+=(int x) { return *this; }
450   explicit GoodIter(void *) {}
451   GoodIter operator++() { return *this; }
452   GoodIter operator--() { return *this; }
453   bool operator!() { return true; }
454   bool operator<(GoodIter a) { return true; }
455   bool operator<=(GoodIter a) { return true; }
456   bool operator>=(GoodIter a) { return false; }
457   typedef int difference_type;
458   typedef std::random_access_iterator_tag iterator_category;
459 };
460 // expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
461 // expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
462 int operator-(GoodIter a, GoodIter b) { return 0; }
463 // expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
464 GoodIter operator-(GoodIter a) { return a; }
465 // expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
466 // expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
467 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
468 // expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
469 GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
470 // expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
471 // expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
472 GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
473 // expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
474 GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
475 
476 int test_with_random_access_iterator() {
477   GoodIter begin, end;
478   Iter0 begin0, end0;
479 #pragma omp target
480 #pragma omp teams
481 #pragma omp distribute parallel for simd
482   for (GoodIter I = begin; I < end; ++I)
483     ++I;
484 #pragma omp target
485 #pragma omp teams
486 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
487 #pragma omp distribute parallel for simd
488   for (GoodIter &I = begin; I < end; ++I)
489     ++I;
490 #pragma omp target
491 #pragma omp teams
492 #pragma omp distribute parallel for simd
493   for (GoodIter I = begin; I >= end; --I)
494     ++I;
495 #pragma omp target
496 #pragma omp teams
497 // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
498 #pragma omp distribute parallel for simd
499   for (GoodIter I(begin); I < end; ++I)
500     ++I;
501 #pragma omp target
502 #pragma omp teams
503 // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
504 #pragma omp distribute parallel for simd
505   for (GoodIter I(nullptr); I < end; ++I)
506     ++I;
507 #pragma omp target
508 #pragma omp teams
509 // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
510 #pragma omp distribute parallel for simd
511   for (GoodIter I(0); I < end; ++I)
512     ++I;
513 #pragma omp target
514 #pragma omp teams
515 // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
516 #pragma omp distribute parallel for simd
517   for (GoodIter I(1, 2); I < end; ++I)
518     ++I;
519 #pragma omp target
520 #pragma omp teams
521 #pragma omp distribute parallel for simd
522   for (begin = GoodIter(0); begin < end; ++begin)
523     ++begin;
524 #pragma omp target
525 #pragma omp teams
526 // expected-error@+3 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
527 // expected-error@+2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
528 #pragma omp distribute parallel for simd
529   for (begin = begin0; begin < end; ++begin)
530     ++begin;
531 #pragma omp target
532 #pragma omp teams
533 // expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
534 #pragma omp distribute parallel for simd
535   for (++begin; begin < end; ++begin)
536     ++begin;
537 #pragma omp target
538 #pragma omp teams
539 #pragma omp distribute parallel for simd
540   for (begin = end; begin < end; ++begin)
541     ++begin;
542 #pragma omp target
543 #pragma omp teams
544 // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
545 #pragma omp distribute parallel for simd
546   for (GoodIter I = begin; I - I; ++I)
547     ++I;
548 #pragma omp target
549 #pragma omp teams
550 // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
551 #pragma omp distribute parallel for simd
552   for (GoodIter I = begin; begin < end; ++I)
553     ++I;
554 #pragma omp target
555 #pragma omp teams
556 // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
557 #pragma omp distribute parallel for simd
558   for (GoodIter I = begin; !I; ++I)
559     ++I;
560 #pragma omp target
561 #pragma omp teams
562 // expected-note@+3 {{loop step is expected to be negative due to this condition}}
563 // expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
564 #pragma omp distribute parallel for simd
565   for (GoodIter I = begin; I >= end; I = I + 1)
566     ++I;
567 #pragma omp target
568 #pragma omp teams
569 #pragma omp distribute parallel for simd
570   for (GoodIter I = begin; I >= end; I = I - 1)
571     ++I;
572 #pragma omp target
573 #pragma omp teams
574 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
575 #pragma omp distribute parallel for simd
576   for (GoodIter I = begin; I >= end; I = -I)
577     ++I;
578 #pragma omp target
579 #pragma omp teams
580 // expected-note@+3 {{loop step is expected to be negative due to this condition}}
581 // expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
582 #pragma omp distribute parallel for simd
583   for (GoodIter I = begin; I >= end; I = 2 + I)
584     ++I;
585 #pragma omp target
586 #pragma omp teams
587 // expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
588 #pragma omp distribute parallel for simd
589   for (GoodIter I = begin; I >= end; I = 2 - I)
590     ++I;
591 #pragma omp target
592 #pragma omp teams
593 // expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
594 #pragma omp distribute parallel for simd
595   for (Iter0 I = begin0; I < end0; ++I)
596     ++I;
597 #pragma omp target
598 #pragma omp teams
599 // Initializer is constructor without params.
600 // expected-error@+3 {{invalid operands to binary expression ('Iter0' and 'int')}}
601 // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
602 #pragma omp distribute parallel for simd
603   for (Iter0 I; I < end0; ++I)
604     ++I;
605   Iter1 begin1, end1;
606 #pragma omp target
607 #pragma omp teams
608 // expected-error@+3 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
609 // expected-error@+2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
610 #pragma omp distribute parallel for simd
611   for (Iter1 I = begin1; I < end1; ++I)
612     ++I;
613 #pragma omp target
614 #pragma omp teams
615 // expected-note@+3 {{loop step is expected to be negative due to this condition}}
616 // expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
617 #pragma omp distribute parallel for simd
618   for (Iter1 I = begin1; I >= end1; ++I)
619     ++I;
620 #pragma omp target
621 #pragma omp teams
622 // expected-error@+5 {{invalid operands to binary expression ('Iter1' and 'float')}}
623 // expected-error@+4 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
624 // Initializer is constructor with all default params.
625 // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
626 #pragma omp distribute parallel for simd
627   for (Iter1 I; I < end1; ++I) {
628   }
629   return 0;
630 }
631 
632 template <typename IT, int ST>
633 class TC {
634 public:
635   int dotest_lt(IT begin, IT end) {
636 #pragma omp target
637 #pragma omp teams
638 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
639 // expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
640 #pragma omp distribute parallel for simd
641     for (IT I = begin; I < end; I = I + ST) {
642       ++I;
643     }
644 #pragma omp target
645 #pragma omp teams
646 // expected-note@+3 {{loop step is expected to be positive due to this condition}}
647 // expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
648 #pragma omp distribute parallel for simd
649     for (IT I = begin; I <= end; I += ST) {
650       ++I;
651     }
652 #pragma omp target
653 #pragma omp teams
654 #pragma omp distribute parallel for simd
655     for (IT I = begin; I < end; ++I) {
656       ++I;
657     }
658   }
659 
660   static IT step() {
661     return IT(ST);
662   }
663 };
664 template <typename IT, int ST = 0>
665 int dotest_gt(IT begin, IT end) {
666 #pragma omp target
667 #pragma omp teams
668 // expected-note@+3 2 {{loop step is expected to be negative due to this condition}}
669 // expected-error@+2 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
670 #pragma omp distribute parallel for simd
671   for (IT I = begin; I >= end; I = I + ST) {
672     ++I;
673   }
674 #pragma omp target
675 #pragma omp teams
676 // expected-note@+3 2 {{loop step is expected to be negative due to this condition}}
677 // expected-error@+2 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
678 #pragma omp distribute parallel for simd
679   for (IT I = begin; I >= end; I += ST) {
680     ++I;
681   }
682 
683 #pragma omp target
684 #pragma omp teams
685 // expected-note@+3 {{loop step is expected to be negative due to this condition}}
686 // expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
687 #pragma omp distribute parallel for simd
688   for (IT I = begin; I >= end; ++I) {
689     ++I;
690   }
691 
692 #pragma omp distribute parallel for simd
693   for (IT I = begin; I < end; I += TC<int, ST>::step()) {
694     ++I;
695   }
696 }
697 
698 void test_with_template() {
699   GoodIter begin, end;
700   TC<GoodIter, 100> t1;
701   TC<GoodIter, -100> t2;
702   t1.dotest_lt(begin, end);
703   t2.dotest_lt(begin, end);         // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
704   dotest_gt(begin, end);            // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
705   dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
706 }
707 
708 void test_loop_break() {
709   const int N = 100;
710   float a[N], b[N], c[N];
711 #pragma omp target
712 #pragma omp teams
713 #pragma omp distribute parallel for simd
714   for (int i = 0; i < 10; i++) {
715     c[i] = a[i] + b[i];
716     for (int j = 0; j < 10; ++j) {
717       if (a[i] > b[j])
718         break; // OK in nested loop
719     }
720     switch (i) {
721     case 1:
722       b[i]++;
723       break;
724     default:
725       break;
726     }
727     if (c[i] > 10)
728       break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
729 
730     if (c[i] > 11)
731       break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
732   }
733 
734 #pragma omp target
735 #pragma omp teams
736 #pragma omp distribute parallel for simd
737   for (int i = 0; i < 10; i++) {
738     for (int j = 0; j < 10; j++) {
739       c[i] = a[i] + b[i];
740       if (c[i] > 10) {
741         if (c[i] < 20) {
742           break; // OK
743         }
744       }
745     }
746   }
747 }
748 
749 void test_loop_eh() {
750   const int N = 100;
751   float a[N], b[N], c[N];
752 #pragma omp target
753 #pragma omp teams
754 #pragma omp distribute parallel for simd
755   for (int i = 0; i < 10; i++) {
756     c[i] = a[i] + b[i];
757     try { // expected-error {{'try' statement cannot be used in OpenMP simd region}}
758       for (int j = 0; j < 10; ++j) {
759         if (a[i] > b[j])
760           throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
761       }
762       throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
763     } catch (float f) {
764       if (f > 0.1)
765         throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
766       return; // expected-error {{cannot return from OpenMP region}}
767     }
768     switch (i) {
769     case 1:
770       b[i]++;
771       break;
772     default:
773       break;
774     }
775     for (int j = 0; j < 10; j++) {
776       if (c[i] > 10)
777         throw c[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
778     }
779   }
780   if (c[9] > 10)
781     throw c[9]; // OK
782 
783 #pragma omp distribute parallel for simd
784   for (int i = 0; i < 10; ++i) {
785     struct S {
786       void g() { throw 0; }
787     };
788   }
789 }
790 
791 void test_loop_firstprivate_lastprivate() {
792   S s(4);
793 #pragma omp target
794 #pragma omp teams
795 #pragma omp distribute parallel for simd lastprivate(s) firstprivate(s)
796   for (int i = 0; i < 16; ++i)
797     ;
798 }
799 
800 void test_ordered() {
801 #pragma omp target
802 #pragma omp teams
803 #pragma omp distribute parallel for simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp distribute parallel for simd'}}
804   for (int i = 0; i < 16; ++i)
805     ;
806 }
807 
808 void test_nowait() {
809 #pragma omp target
810 #pragma omp teams
811 // expected-error@+1 2 {{unexpected OpenMP clause 'nowait' in directive '#pragma omp distribute parallel for simd'}}
812 #pragma omp distribute parallel for simd nowait nowait // expected-error {{directive '#pragma omp distribute parallel for simd' cannot contain more than one 'nowait' clause}}
813   for (int i = 0; i < 16; ++i)
814     ;
815 }
816 
817