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