// { dg-do run } // { dg-additional-options "-std=c++17" } typedef __PTRDIFF_TYPE__ ptrdiff_t; extern "C" void abort (); namespace std { template struct tuple_size; template struct tuple_element; } template class I { public: typedef ptrdiff_t difference_type; I (); ~I (); I (T *); I (const I &); T &operator * (); T *operator -> (); T &operator [] (const difference_type &) const; I &operator = (const I &); I &operator ++ (); I operator ++ (int); I &operator -- (); I operator -- (int); I &operator += (const difference_type &); I &operator -= (const difference_type &); I operator + (const difference_type &) const; I operator - (const difference_type &) const; template friend bool operator == (I &, I &); template friend bool operator == (const I &, const I &); template friend bool operator < (I &, I &); template friend bool operator < (const I &, const I &); template friend bool operator <= (I &, I &); template friend bool operator <= (const I &, const I &); template friend bool operator > (I &, I &); template friend bool operator > (const I &, const I &); template friend bool operator >= (I &, I &); template friend bool operator >= (const I &, const I &); template friend typename I::difference_type operator - (I &, I &); template friend typename I::difference_type operator - (const I &, const I &); template friend I operator + (typename I::difference_type , const I &); private: T *p; }; template I::I () : p (0) {} template I::~I () {} template I::I (T *x) : p (x) {} template I::I (const I &x) : p (x.p) {} template T &I::operator * () { return *p; } template T *I::operator -> () { return p; } template T &I::operator [] (const difference_type &x) const { return p[x]; } template I &I::operator = (const I &x) { p = x.p; return *this; } template I &I::operator ++ () { ++p; return *this; } template I I::operator ++ (int) { return I (p++); } template I &I::operator -- () { --p; return *this; } template I I::operator -- (int) { return I (p--); } template I &I::operator += (const difference_type &x) { p += x; return *this; } template I &I::operator -= (const difference_type &x) { p -= x; return *this; } template I I::operator + (const difference_type &x) const { return I (p + x); } template I I::operator - (const difference_type &x) const { return I (p - x); } template bool operator == (I &x, I &y) { return x.p == y.p; } template bool operator == (const I &x, const I &y) { return x.p == y.p; } template bool operator != (I &x, I &y) { return !(x == y); } template bool operator != (const I &x, const I &y) { return !(x == y); } template bool operator < (I &x, I &y) { return x.p < y.p; } template bool operator < (const I &x, const I &y) { return x.p < y.p; } template bool operator <= (I &x, I &y) { return x.p <= y.p; } template bool operator <= (const I &x, const I &y) { return x.p <= y.p; } template bool operator > (I &x, I &y) { return x.p > y.p; } template bool operator > (const I &x, const I &y) { return x.p > y.p; } template bool operator >= (I &x, I &y) { return x.p >= y.p; } template bool operator >= (const I &x, const I &y) { return x.p >= y.p; } template typename I::difference_type operator - (I &x, I &y) { return x.p - y.p; } template typename I::difference_type operator - (const I &x, const I &y) { return x.p - y.p; } template I operator + (typename I::difference_type x, const I &y) { return I (x + y.p); } template class J { public: J(const I &x, const I &y) : b (x), e (y) {} const I &begin (); const I &end (); private: I b, e; }; template const I &J::begin () { return b; } template const I &J::end () { return e; } template class K { public: K (); ~K (); template T &get () { if (N == 0) return c; else if (N == 1) return b; return a; } T a, b, c; }; template K::K () : a {}, b {}, c {} {} template K::~K () {} template struct std::tuple_size> { static constexpr int value = 3; }; template struct std::tuple_element> { using type = T; }; template class L { public: L (); ~L (); T a, b, c; }; template L::L () : a {}, b {}, c {} {} template L::~L () {} int a[2000]; long b[40]; short c[50]; int d[1024]; K e[1089]; L f[1093]; int results[2000]; template static inline void baz (I &i) { results[*i]++; } static inline void baz (int i) { results[i]++; } void f1 () { #pragma omp parallel loop shared(a) default(none) for (auto i : a) baz (i); } void f2 () { #pragma omp loop order(concurrent) bind(parallel) for (auto &i : a) if (&i != &a[i]) abort (); else baz (i); } void f3 () { #pragma omp teams loop collapse(3) default(none) shared(b, c) for (auto &i : b) for (int j = 9; j < 10; j++) for (auto k : c) if (&i != &b[i] || i < 0 || i >= 40 || j != 9 || k < 0 || k >= 50) abort (); else baz (i * 50 + k); } void f4 (J j) { #pragma omp loop bind(teams) for (auto &i : j) if (&i != &a[i]) abort (); else baz (i); } void f5 () { #pragma omp loop bind(thread) for (auto i : d) results[i % 1024] += 2 * ((unsigned) i >> 10) + 1; } void f6 (J> j) { #pragma omp loop bind(parallel) for (auto & [k, l, m] : j) if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2) abort (); else baz (m); } void f7 (J> j) { #pragma omp parallel loop default(none) shared(j, f) for (auto & [k, l, m] : j) if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5) abort (); else baz (k); } void f8 (J> j) { #pragma omp parallel loop default(none) shared(j) for (auto [k, l, m] : j) if (k != m * 3 || l != m * 2) abort (); else baz (m); } void f9 (J> j) { #pragma omp teams loop default(none) shared(j) for (auto [k, l, m] : j) if (l != k * 4 || m != k * 5) abort (); else baz (k); } template void f10 () { #pragma omp loop bind(teams) for (auto i : a) baz (i); } template void f11 () { #pragma omp loop bind(thread) for (auto &i : a) if (&i != &a[i]) abort (); else baz (i); } template void f12 () { #pragma omp parallel loop collapse(3) default(none) shared(a, b, c) bind(parallel) for (auto &i : b) for (I j = I (&a[9]); j < I (&a[10]); j++) for (auto k : c) if (&i != &b[i] || i < 0 || i >= 40 || *j != 9 || k < 0 || k >= 50) abort (); else baz (i * 50 + k); } template void f13 (J j) { #pragma omp loop bind(thread) for (auto &i : j) if (&i != &a[i]) abort (); else baz (i); } template void f14 () { #pragma omp parallel loop default(none) shared(d, results) for (auto i : d) results[i % N] += 2 * ((unsigned) i >> 10) + 1; } template void f15 (J> j) { #pragma omp parallel loop default(none) shared(j, e) bind(parallel) for (auto & [k, l, m] : j) if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2) abort (); else baz (m); } template void f16 (J> j) { #pragma omp loop bind(parallel) for (auto & [k, l, m] : j) if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5) abort (); else baz (k); } template void f17 (J> j) { #pragma omp parallel loop default(none) shared(j) for (auto [k, l, m] : j) if (k != m * 3 || l != m * 2) abort (); else baz (m); } template void f18 (J> j) { #pragma omp teams loop default(none) shared(j) for (auto [k, l, m] : j) if (l != k * 4 || m != k * 5) abort (); else baz (k); } #define check(expr) \ for (int i = 0; i < 2000; i++) \ if (expr) \ { \ if (results[i] != 1) \ abort (); \ results[i] = 0; \ } \ else if (results[i]) \ abort () int main () { for (int i = 0; i < 2000; i++) a[i] = i; for (int i = 0; i < 40; i++) b[i] = i; for (int i = 0; i < 50; i++) c[i] = i; for (int i = 0; i < 1024; i++) d[i] = i; for (int i = 0; i < 1089; i++) { e[i].a = i; e[i].b = 2 * i; e[i].c = 3 * i; } for (int i = 0; i < 1093; i++) { f[i].a = i; f[i].b = 4 * i; f[i].c = 5 * i; } f1 (); check (1); #pragma omp parallel f2 (); check (1); f3 (); check (1); #pragma omp teams f4 (J (&a[14], &a[1803])); check (i >= 14 && i < 1803); f5 (); check (i >= 0 && i < 1024); #pragma omp parallel f6 (J> (&e[19], &e[1029])); check (i >= 19 && i < 1029); f7 (J> (&f[15], &f[1091])); check (i >= 15 && i < 1091); f8 (J> (&e[27], &e[1037])); check (i >= 27 && i < 1037); f9 (J> (&f[1], &f[1012])); check (i >= 1 && i < 1012); #pragma omp teams f10 <0> (); check (1); f11 <1> (); check (1); f12 <2> (); check (1); f13 (J (&a[24], &a[1703])); check (i >= 24 && i < 1703); f14 <1024> (); check (i >= 0 && i < 1024); f15 (J> (&e[39], &e[929])); check (i >= 39 && i < 929); #pragma omp parallel f16 (J> (&f[17], &f[1071])); check (i >= 17 && i < 1071); f17 <3> (J> (&e[7], &e[1017])); check (i >= 7 && i < 1017); f18 <5> (J> (&f[121], &f[1010])); check (i >= 121 && i < 1010); }