aboutsummaryrefslogtreecommitdiff
path: root/libgomp/testsuite/libgomp.c++
diff options
context:
space:
mode:
Diffstat (limited to 'libgomp/testsuite/libgomp.c++')
-rw-r--r--libgomp/testsuite/libgomp.c++/depend-1.C31
-rw-r--r--libgomp/testsuite/libgomp.c++/depend-iterator-1.C167
-rw-r--r--libgomp/testsuite/libgomp.c++/depobj-1.C103
-rw-r--r--libgomp/testsuite/libgomp.c++/for-16.C218
-rw-r--r--libgomp/testsuite/libgomp.c++/for-21.C291
-rw-r--r--libgomp/testsuite/libgomp.c++/for-22.C314
-rw-r--r--libgomp/testsuite/libgomp.c++/for-23.C416
-rw-r--r--libgomp/testsuite/libgomp.c++/for-24.C427
-rw-r--r--libgomp/testsuite/libgomp.c++/for-25.C420
-rw-r--r--libgomp/testsuite/libgomp.c++/for-26.C422
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-1.C63
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-10.C125
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-11.C237
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-12.C321
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-13.C342
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-14.C72
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-15.C75
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-16.C130
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-17.C300
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-18.C325
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-19.C343
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-2.C119
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-3.C126
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-4.C238
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-5.C320
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-6.C341
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-7.C145
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-8.C70
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-9.C128
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C153
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C253
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C314
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C315
33 files changed, 7664 insertions, 0 deletions
diff --git a/libgomp/testsuite/libgomp.c++/depend-1.C b/libgomp/testsuite/libgomp.c++/depend-1.C
new file mode 100644
index 0000000..71a24d1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/depend-1.C
@@ -0,0 +1,31 @@
+extern "C" void abort ();
+int a, b, c, d, e;
+
+void
+foo (int &x, bool y)
+{
+ #pragma omp task depend (out: x)
+ a = 1;
+ #pragma omp task depend (out: y ? b : c)
+ (y ? b : c) = 2;
+ #pragma omp task depend (inout: --d)
+ d += 4;
+ #pragma omp task depend (in : a, (y ? b : c), d)
+ e = a + b * 10 + c * 100 + d * 1000;
+}
+
+int
+main ()
+{
+ #pragma omp parallel
+ #pragma omp single
+ foo (a, true);
+ if (e != 1 + 20 + 0 + 3000)
+ abort ();
+ a = b = c = d = e = 0;
+ #pragma omp parallel
+ #pragma omp single
+ foo (a, false);
+ if (e != 1 + 0 + 200 + 3000)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/depend-iterator-1.C b/libgomp/testsuite/libgomp.c++/depend-iterator-1.C
new file mode 100644
index 0000000..2cff5e8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/depend-iterator-1.C
@@ -0,0 +1,167 @@
+extern "C" void abort ();
+int arr[64], arr2[64], arr3[64];
+
+int *
+foo (int x, int y, long z)
+{
+ int v;
+ switch (x)
+ {
+ case 1:
+ if (z != 0 || y < 0 || y >= 64)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = arr2[y];
+ arr2[y]++;
+ }
+ if (v != 0) abort ();
+ return &arr[y];
+ case 2:
+ if (y < 0 || y > 60 || (y & 3) || z < 0 || z >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 4;
+ return &arr[y + z];
+ case 3:
+ if (z < 0 || z > 60 || (z & 3) || y < 0 || y >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 16;
+ return &arr[y + z];
+ case 4:
+ if (y != 0 || z > 64 || z <= 0)
+ abort ();
+ #pragma omp atomic
+ arr2[z - 1] = arr2[z - 1] + 64;
+ return &arr[z - 1];
+ case 5:
+ if ((y & 3) != 0 || y < 64 || y >= 96
+ || (z & 127) != 0 || z < 512 || z >= 1024)
+ abort ();
+ y = (y - 64) + (z - 512) / 128;
+ #pragma omp atomic
+ arr2[y] = arr2[y] + 256;
+ return &arr[y];
+ case 6:
+ if ((y & 3) != 0 || y <= 64 || y > 96
+ || (z & 127) != 1 || z <= 513 || z > 1025)
+ abort ();
+ y = (y - 68) + (z - 641) / 128;
+ #pragma omp atomic
+ arr2[y] = arr2[y] + 1024;
+ return &arr[y];
+ default:
+ abort ();
+ }
+}
+
+volatile int beg, end, step, step2;
+volatile unsigned int begu, endu;
+
+template <int N>
+void
+bar ()
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (j=i:i+1) , out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (int k=beg:end:step,long int l=0:4:1) , inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (int *p=&arr3[64]:&arr3[0]:-1), inout : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ #pragma omp task depend (iterator (unsigned n=begu:endu:step2, unsigned int o = 512: 1024U: (unsigned char) 128), inout : \
+ foo (5, n + 128, o)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 3)
+ abort ();
+ else
+ arr[i] = arr[i] + 4;
+ #pragma omp task depend (iterator (int unsigned p=endu:begu:step,unsigned q= 1025U:513U:(signed char) -128), in : \
+ foo (6, p + 128, q)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 7)
+ abort ();
+ else
+ arr[i] = arr[i] + 8;
+ }
+}
+
+template <typename A, typename B, typename C, typename D, typename E, typename F>
+void
+baz (A beg, A end, A step, D begu, D endu, A step2)
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (A j=i:i+1),out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (A k=beg:end:step,B l=0:4:1), inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (C p=&arr3[64]:&arr3[0]:-1), in : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ #pragma omp task depend (iterator (D n=begu:endu:step2, D o = 512: 1024U:(E) 128), inout : \
+ foo (5, n + 128, o)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 3)
+ abort ();
+ else
+ arr[i] = arr[i] + 4;
+ #pragma omp task depend (iterator (D p=endu:begu:step,D q= 1025U:513U:(F) -128), in : \
+ foo (6, p + 128, q)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 7)
+ abort ();
+ else
+ arr[i] = arr[i] + 8;
+ }
+}
+
+int
+main ()
+{
+ int m;
+ beg = 60;
+ end = -4;
+ step = -4;
+ step2 = 4;
+ begu = -64U;
+ endu = -32U;
+ bar<0> ();
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 15 || arr2[m] != (m < 32 ? 1365 : 85))
+ abort ();
+ else
+ arr[m] = arr2[m] = 0;
+ baz<int, long int, int *, unsigned int, unsigned char, signed char> (beg, end, step, begu, endu, step2);
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 15 || arr2[m] != (m < 32 ? 1365 : 85))
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/depobj-1.C b/libgomp/testsuite/libgomp.c++/depobj-1.C
new file mode 100644
index 0000000..91edf8c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/depobj-1.C
@@ -0,0 +1,103 @@
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (omp_depend_t &d1, omp_depend_t *d2)
+{
+ int x = 1;
+ #pragma omp depobj (d1) depend(in: x)
+ #pragma omp depobj (*d2) depend(in: x)
+
+ #pragma omp depobj (d2[0]) update(out)
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(depobj:*d2)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj : d1)
+ if (x != 2)
+ abort ();
+ }
+ #pragma omp depobj (d2[0]) destroy
+ #pragma omp depobj (d1) destroy
+}
+
+template <typename T>
+void
+dep2 (T &d2)
+{
+ T d1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ #pragma omp depobj (d1) depend(out: x)
+ #pragma omp depobj (*&d2) depend (in:x)
+ #pragma omp depobj(d2)update(in)
+ #pragma omp task shared (x) depend(depobj :d1)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj: d2)
+ if (x != 2)
+ abort ();
+ #pragma omp taskwait
+ #pragma omp depobj(d1)destroy
+ #pragma omp depobj((&d2)[0]) destroy
+ }
+}
+
+template <typename T>
+void
+dep3 (void)
+{
+ T d[2];
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp depobj(d[0]) depend(out:x)
+ #pragma omp depobj(d[1]) depend(in: x)
+ #pragma omp task shared (x) depend(depobj:*d)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj:*(d + 1))
+ if (x != 2)
+ abort ();
+ }
+ }
+ #pragma omp depobj(d[0]) destroy
+ #pragma omp depobj(d[1]) destroy
+}
+
+int xx;
+omp_depend_t dd1, dd2;
+
+template <int N>
+void
+antidep (void)
+{
+ xx = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared(xx) depend(depobj:dd2)
+ if (xx != 1)
+ abort ();
+ #pragma omp task shared(xx) depend(depobj:dd1)
+ xx = 2;
+ }
+}
+
+int
+main ()
+{
+ omp_depend_t d1, d2, d3;
+ dep (d1, &d2);
+ dep2 <omp_depend_t> (d3);
+ dep3 <omp_depend_t> ();
+ #pragma omp depobj (dd1) depend (inout: xx)
+ #pragma omp depobj (dd2) depend (in : xx)
+ antidep <0> ();
+ #pragma omp depobj (dd2) destroy
+ #pragma omp depobj (dd1) destroy
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-16.C b/libgomp/testsuite/libgomp.c++/for-16.C
new file mode 100644
index 0000000..e7e5b85
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-16.C
@@ -0,0 +1,218 @@
+// PR c++/86443
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 (J<int> j)
+{
+#pragma omp distribute parallel for default(none)
+ for (I<int> i = j.begin (); i < j.end (); i += 3)
+ baz (*i);
+}
+
+void
+f2 (J<int> j)
+{
+ I<int> i;
+#pragma omp distribute parallel for default(none)
+ for (i = j.begin (); i < j.end (); ++i)
+ baz (*i);
+}
+
+template <int N>
+void
+f3 (J<int> j)
+{
+#pragma omp distribute parallel for default(none)
+ for (I<int> i = j.begin (); i < j.end (); i += 6)
+ baz (*i);
+}
+
+template <int N>
+void
+f4 (J<int> j)
+{
+ I<int> i;
+#pragma omp distribute parallel for default(none)
+ for (i = j.begin (); i < j.end (); i += 9)
+ baz (*i);
+}
+
+template <typename T>
+void
+f5 (J<T> j)
+{
+#pragma omp distribute parallel for default(none)
+ for (I<T> i = j.begin (); i < j.end (); i += 4)
+ baz (*i);
+}
+
+template <typename T>
+void
+f6 (J<T> j)
+{
+ I<T> i;
+#pragma omp distribute parallel for default(none)
+ for (i = j.begin (); i < j.end (); i += 7)
+ baz (*i);
+}
+
+#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 ()
+{
+ int a[2000];
+ for (int i = 0; i < 2000; i++)
+ a[i] = i;
+ #pragma omp teams
+ {
+ J<int> j (&a[75], &a[1945]);
+ f1 (j);
+ }
+ check (i >= 75 && i < 1945 && (i - 75) % 3 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[63], &a[1949]);
+ f2 (j);
+ }
+ check (i >= 63 && i < 1949);
+ #pragma omp teams
+ {
+ J<int> j (&a[58], &a[1979]);
+ f3 <2> (j);
+ }
+ check (i >= 58 && i < 1979 && (i - 58) % 6 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[59], &a[1981]);
+ f4 <9> (j);
+ }
+ check (i >= 59 && i < 1981 && (i - 59) % 9 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[52], &a[1972]);
+ f5 (j);
+ }
+ check (i >= 52 && i < 1972 && (i - 52) % 4 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[31], &a[1827]);
+ f6 (j);
+ }
+ check (i >= 31 && i < 1827 && (i - 31) % 7 == 0);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-21.C b/libgomp/testsuite/libgomp.c++/for-21.C
new file mode 100644
index 0000000..fc0cb0a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-21.C
@@ -0,0 +1,291 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+f1 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x; i != y; i++)
+ baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for private(i)
+ for (i = x; i != y - 1; i = 2 - 8 + 7 + i)
+ baz (i);
+}
+
+template <typename T>
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x; i != y; i = i + 9 - 8)
+ baz (i);
+}
+
+template <typename T>
+void
+f4 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x + 2000 - 64; i != y + 10; --i)
+ baz (i);
+}
+
+void
+f5 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x + 2000 - 64; i != y + 10; i--)
+ baz (i);
+}
+
+template <int N>
+void
+f6 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x + 2000 - 64; i != y + 10; i = i - 12 + 11)
+ {
+ I<int> j = i + N;
+ baz (j);
+ }
+}
+
+template <int N>
+void
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (i = x - 10; i != y + 10; i += N)
+ baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+ I<int> i;
+#pragma omp parallel for
+ for (i = j.begin (); i != j.end () + N; i += 1)
+ baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const I<T> &x, const I<T> &y)
+{
+#pragma omp parallel for
+ for (I<T> i = x; i != y; i = i - N)
+ baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const I<T> &x, const I<T> &y)
+{
+ I<T> i;
+#pragma omp parallel for
+ for (i = x; i != y; i = i + N)
+ baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+ {
+#pragma omp for nowait
+ for (T i = x; i != y; i++)
+ baz (i);
+#pragma omp single
+ {
+ T j = y + 3;
+ baz (j);
+ }
+ }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+ T i;
+#pragma omp parallel for
+ for (i = x; i != y; --i)
+ baz (i);
+}
+
+template <int N>
+struct K
+{
+ template <typename T>
+ static void
+ f13 (const T &x, const T &y)
+ {
+#pragma omp parallel for
+ for (T i = x; i != y + N; i += N)
+ baz (i);
+ }
+};
+
+#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 ()
+{
+ int a[2000];
+ long b[2000];
+ for (int i = 0; i < 2000; i++)
+ {
+ a[i] = i;
+ b[i] = i;
+ }
+ f1 (&a[10], &a[1990]);
+ check (i >= 10 && i < 1990);
+ f2 (&a[0], &a[1999]);
+ check (i < 1998);
+ f3<char> (&a[20], &a[1837]);
+ check (i >= 20 && i < 1837);
+ f4<int> (&a[0], &a[30]);
+ check (i > 40 && i <= 2000 - 64);
+ f5 (&a[0], &a[100]);
+ check (i > 110 && i <= 2000 - 64);
+ f6<-10> (&a[10], &a[110]);
+ check (i > 110 && i <= 2000 - 64);
+ f7<1> (I<int> (), &a[12], &a[1800]);
+ check (i >= 2 && i < 1810);
+ f8<121> (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1924);
+ f9<int, -1> (&a[33], &a[1967]);
+ check (i >= 33 && i < 1967);
+ f10<int, -1> (&a[1939], &a[17]);
+ check (i > 17 && i <= 1939);
+ f11<I<int> > (&a[16], &a[1981]);
+ check ((i >= 16 && i < 1981) || i == 1984);
+ f12<I<int> > (&a[1761], &a[37]);
+ check (i > 37 && i <= 1761);
+ K<1>::f13<I<int> > (&a[1], &a[1935]);
+ check (i >= 1 && i < 1936);
+ f9<long, 1 - 2> (&b[33], &b[1967]);
+ check (i >= 33 && i < 1967);
+ f10<long, -1> (&b[1939], &b[17]);
+ check (i > 17 && i <= 1939);
+ f11<I<long> > (&b[16], &b[1981]);
+ check ((i >= 16 && i < 1981) || i == 1984);
+ f12<I<long> > (&b[1761], &b[37]);
+ check (i > 37 && i <= 1761);
+ K<1>::f13<I<long> > (&b[1], &b[1935]);
+ check (i >= 1 && i < 1936);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-22.C b/libgomp/testsuite/libgomp.c++/for-22.C
new file mode 100644
index 0000000..35fcf1f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-22.C
@@ -0,0 +1,314 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () { p = (T *) 0; }
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+I<int>
+f1 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel shared(i)
+ {
+#pragma omp for lastprivate (i) schedule(runtime)
+ for (i = x; i != y; i++)
+ baz (i);
+#pragma omp single
+ i += 3;
+ }
+ return I<int> (i);
+}
+
+I<int>
+f2 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x; i != y - 1; i = 2 - 8 + 7 + i)
+ baz (i);
+ return I<int> (i);
+}
+
+template <typename T>
+I<int>
+f3 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel
+ #pragma omp for lastprivate (i)
+ for (i = x; i != y; i = i + 9 - 8)
+ baz (i);
+ return i;
+}
+
+template <typename T>
+I<int>
+f4 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x + 2000 - 64; i != y + 10; --i)
+ baz (i);
+ return I<int> (i);
+}
+
+template <typename T>
+I<int>
+f5 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x + 2000 - 64; i != y + T (10); i--)
+ baz (i);
+ return i;
+}
+
+template <typename T>
+I<int>
+f6 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate (i)
+ for (i = x + 2000 - 64; i != y + 10; i = i - T (12) + T (11))
+ {
+ I<int> j = i + -10;
+ baz (j);
+ }
+ return I<int> (i);
+}
+
+template <int N>
+I<int>
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for lastprivate(i)
+ for (i = x - 10; i != y + 10; i += N)
+ baz (i);
+ return I<int> (i);
+}
+
+template <int N>
+I<int>
+f8 (J<int> j)
+{
+ I<int> i;
+#pragma omp parallel shared \
+(i)
+#pragma omp for lastprivate (i)
+ for (i = j.begin (); i != j.end () + N; i += 1)
+ baz (i);
+ return i;
+}
+
+I<int> i9;
+
+template <long N>
+I<int> &
+f9 (J<int> j)
+{
+#pragma omp parallel for lastprivate(i9)
+ for (i9 = j.begin (); i9 != j.end () - N; i9 = i9 - N)
+ baz (i9);
+ return i9;
+}
+
+template <typename T, int N>
+I<T>
+f10 (const I<T> &x, const I<T> &y)
+{
+ I<T> i;
+#pragma omp parallel for lastprivate (i)
+ for (i = x; i != y; i = i + N)
+ baz (i);
+ return i;
+}
+
+template <typename T, typename U>
+T
+f11 (T i, const T &x, const T &y)
+{
+#pragma omp parallel
+ {
+#pragma omp for lastprivate (i)
+ for (i = x + U (0); i != y + U (2 - 2); i = U(3) + U(-2) + i)
+ baz (i);
+#pragma omp single
+ {
+ T j = y + 3;
+ baz (j);
+ }
+ }
+ return i;
+}
+
+template <typename T>
+T
+f12 (const T &x, const T &y)
+{
+ T i;
+#pragma omp parallel for lastprivate (i)
+ for (i = x; i != y; --i)
+ baz (i);
+ return i;
+}
+
+#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 ()
+{
+ int a[2000];
+ long b[2000];
+ for (int i = 0; i < 2000; i++)
+ {
+ a[i] = i;
+ b[i] = i;
+ }
+ if (*f1 (&a[10], &a[1990]) != 1993)
+ abort ();
+ check (i >= 10 && i < 1990);
+ if (*f2 (&a[0], &a[1999]) != 1998)
+ abort ();
+ check (i < 1998);
+ if (*f3<char> (&a[20], &a[1837]) != 1837)
+ abort ();
+ check (i >= 20 && i < 1837);
+ if (*f4<int> (&a[0], &a[30]) != 40)
+ abort ();
+ check (i > 40 && i <= 2000 - 64);
+ if (*f5<int> (&a[0], &a[100]) != 110)
+ abort ();
+ check (i > 110 && i <= 2000 - 64);
+ if (*f6<int> (&a[10], &a[110]) != 120)
+ abort ();
+ check (i > 110 && i <= 2000 - 64);
+ if (*f7<1> (I<int> (), &a[12], &a[1800]) != 1810)
+ abort ();
+ check (i >= 2 && i < 1810);
+ if (*f8<121> (J<int> (&a[14], &a[1803])) != 1924)
+ abort ();
+ check (i >= 14 && i < 1924);
+ if (*f9<-1> (J<int> (&a[33], &a[1967])) != 1968)
+ abort ();
+ check (i >= 33 && i <= 1967);
+ if (*f10<int, -1> (&a[1939], &a[17]) != 17)
+ abort ();
+ check (i > 17 && i <= 1939);
+ if (*f11<I<int>, int> (I<int> (), &a[16], &a[1981]) != 1981)
+ abort ();
+ check ((i >= 16 && i < 1981) || i == 1984);
+ if (*f12<I<int> > (&a[1761], &a[37]) != 37)
+ abort ();
+ check (i > 37 && i <= 1761);
+ if (*f10<long, -1> (&b[1939], &b[17]) != 17)
+ abort ();
+ check (i > 17 && i <= 1939);
+ if (*f11<I<long>, long> (I<long> (), &b[16], &b[1981]) != 1981)
+ abort ();
+ check ((i >= 16 && i < 1981) || i == 1984);
+ if (*f12<I<long> > (&b[1761], &b[37]) != 37)
+ abort ();
+ check (i > 37 && i <= 1761);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-23.C b/libgomp/testsuite/libgomp.c++/for-23.C
new file mode 100644
index 0000000..e0d7b7a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-23.C
@@ -0,0 +1,416 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+template <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+template <typename T>
+class K
+{
+public:
+ K ();
+ ~K ();
+ template <int N> T &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ T a, b, c;
+};
+
+template <typename T> K<T>::K () : a {}, b {}, c {} {}
+template <typename T> K<T>::~K () {}
+template <typename T> struct std::tuple_size<K<T>> { static constexpr int value = 3; };
+template <typename T, int N> struct std::tuple_element<N, K<T>> { using type = T; };
+
+template <typename T>
+class L
+{
+public:
+ L ();
+ ~L ();
+ T a, b, c;
+};
+
+template <typename T> L<T>::L () : a {}, b {}, c {} {}
+template <typename T> L<T>::~L () {}
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K<int> e[1089];
+L<int> f[1093];
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp parallel for 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<int> j)
+{
+#pragma omp parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K<int>> j)
+{
+#pragma omp parallel for default(none) shared(j, e)
+ 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<L<int>> j)
+{
+#pragma omp parallel for 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<K<int>> j)
+{
+#pragma omp parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L<int>> j)
+{
+#pragma omp parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp parallel for collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&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 <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<K<T>> j)
+{
+#pragma omp parallel for default(none) shared(j, e)
+ 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 <typename T>
+void
+f16 (J<L<T>> j)
+{
+#pragma omp parallel for 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);
+}
+
+template <int N>
+void
+f17 (J<K<int>> j)
+{
+#pragma omp parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L<int>> j)
+{
+#pragma omp parallel for 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);
+ f2 ();
+ check (1);
+ f3 ();
+ check (1);
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ f5 ();
+ check (i >= 0 && i < 1024);
+ f6 (J<K<int>> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ f7 (J<L<int>> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ f8 (J<K<int>> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ f9 (J<L<int>> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ f10 <0> ();
+ check (1);
+ f11 <1> ();
+ check (1);
+ f12 <2> ();
+ check (1);
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ f15 (J<K<int>> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ f16 (J<L<int>> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ f17 <3> (J<K<int>> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ f18 <5> (J<L<int>> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-24.C b/libgomp/testsuite/libgomp.c++/for-24.C
new file mode 100644
index 0000000..cb14add
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-24.C
@@ -0,0 +1,427 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+#pragma omp declare target
+template <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+struct K
+{
+ template <int N> int &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ int a, b, c;
+};
+
+template <> struct std::tuple_size<K> { static constexpr int value = 3; };
+template <int N> struct std::tuple_element<N, K> { using type = int; };
+
+struct L
+{
+ int a, b, c;
+};
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K e[1089];
+L f[1093];
+#pragma omp end declare target
+
+int results[2000];
+
+#pragma omp declare target
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp distribute parallel for 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<int> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ 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<L> j)
+{
+#pragma omp distribute parallel for 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<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp distribute parallel for collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&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 <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ 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 <typename T>
+void
+f16 (J<T> j)
+{
+#pragma omp distribute parallel for 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);
+}
+
+template <int N>
+void
+f17 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+#pragma omp end declare target
+
+#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;
+ }
+ #pragma omp target update to (a, b, c, d, e, f)
+ #pragma omp target teams map (tofrom: results)
+ f1 ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f2 ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f3 ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ #pragma omp target teams map (tofrom: results)
+ f5 ();
+ check (i >= 0 && i < 1024);
+ #pragma omp target teams map (tofrom: results)
+ f6 (J<K> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ #pragma omp target teams map (tofrom: results)
+ f7 (J<L> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ #pragma omp target teams map (tofrom: results)
+ f8 (J<K> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ #pragma omp target teams map (tofrom: results)
+ f9 (J<L> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ #pragma omp target teams map (tofrom: results)
+ f10 <0> ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f11 <1> ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f12 <2> ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ #pragma omp target teams map (tofrom: results)
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ #pragma omp target teams map (tofrom: results)
+ f15 (J<K> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ #pragma omp target teams map (tofrom: results)
+ f16 (J<L> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ #pragma omp target teams map (tofrom: results)
+ f17 <3> (J<K> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ #pragma omp target teams map (tofrom: results)
+ f18 <5> (J<L> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-25.C b/libgomp/testsuite/libgomp.c++/for-25.C
new file mode 100644
index 0000000..3fecb48
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-25.C
@@ -0,0 +1,420 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+template <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+template <typename T>
+class K
+{
+public:
+ K ();
+ ~K ();
+ template <int N> T &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ T a, b, c;
+};
+
+template <typename T> K<T>::K () : a {}, b {}, c {} {}
+template <typename T> K<T>::~K () {}
+template <typename T> struct std::tuple_size<K<T>> { static constexpr int value = 3; };
+template <typename T, int N> struct std::tuple_element<N, K<T>> { using type = T; };
+
+template <typename T>
+class L
+{
+public:
+ L ();
+ ~L ();
+ T a, b, c;
+};
+
+template <typename T> L<T>::L () : a {}, b {}, c {} {}
+template <typename T> L<T>::~L () {}
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K<int> e[1089];
+L<int> f[1093];
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp taskloop 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<int> j)
+{
+#pragma omp taskloop default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp taskloop simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K<int>> j)
+{
+#pragma omp taskloop default(none) shared(j, e)
+ 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<L<int>> j)
+{
+#pragma omp taskloop 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<K<int>> j)
+{
+#pragma omp taskloop default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L<int>> j)
+{
+#pragma omp taskloop default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp taskloop collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&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 <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp taskloop default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp taskloop simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<K<T>> j)
+{
+#pragma omp taskloop default(none) shared(j, e)
+ 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 <typename T>
+void
+f16 (J<L<T>> j)
+{
+#pragma omp taskloop 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);
+}
+
+template <int N>
+void
+f17 (J<K<int>> j)
+{
+#pragma omp taskloop default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L<int>> j)
+{
+#pragma omp taskloop 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;
+ }
+ #pragma omp parallel
+ #pragma omp single
+ {
+ f1 ();
+ check (1);
+ f2 ();
+ check (1);
+ f3 ();
+ check (1);
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ f5 ();
+ check (i >= 0 && i < 1024);
+ f6 (J<K<int>> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ f7 (J<L<int>> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ f8 (J<K<int>> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ f9 (J<L<int>> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ f10 <0> ();
+ check (1);
+ f11 <1> ();
+ check (1);
+ f12 <2> ();
+ check (1);
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ f15 (J<K<int>> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ f16 (J<L<int>> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ f17 <3> (J<K<int>> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ f18 <5> (J<L<int>> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-26.C b/libgomp/testsuite/libgomp.c++/for-26.C
new file mode 100644
index 0000000..bb7ae11
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-26.C
@@ -0,0 +1,422 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+template <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+struct K
+{
+ template <int N> int &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ int a, b, c;
+};
+
+template <> struct std::tuple_size<K> { static constexpr int value = 3; };
+template <int N> struct std::tuple_element<N, K> { using type = int; };
+
+struct L
+{
+ int a, b, c;
+};
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K e[1089];
+L f[1093];
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp distribute parallel for 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<int> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ 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<L> j)
+{
+#pragma omp distribute parallel for 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<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp distribute parallel for collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&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 <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ 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 <typename T>
+void
+f16 (J<T> j)
+{
+#pragma omp distribute parallel for 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);
+}
+
+template <int N>
+void
+f17 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L> j)
+{
+#pragma omp distribute parallel for 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;
+ }
+ #pragma omp teams
+ f1 ();
+ check (1);
+ #pragma omp teams
+ f2 ();
+ check (1);
+ #pragma omp teams
+ f3 ();
+ check (1);
+ #pragma omp teams
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ #pragma omp teams
+ f5 ();
+ check (i >= 0 && i < 1024);
+ #pragma omp teams
+ f6 (J<K> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ #pragma omp teams
+ f7 (J<L> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ #pragma omp teams
+ f8 (J<K> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ #pragma omp teams
+ f9 (J<L> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ #pragma omp teams
+ f10 <0> ();
+ check (1);
+ #pragma omp teams
+ f11 <1> ();
+ check (1);
+ #pragma omp teams
+ f12 <2> ();
+ check (1);
+ #pragma omp teams
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ #pragma omp teams
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ #pragma omp teams
+ f15 (J<K> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ #pragma omp teams
+ f16 (J<L> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ #pragma omp teams
+ f17 <3> (J<K> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ #pragma omp teams
+ f18 <5> (J<L> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-1.C b/libgomp/testsuite/libgomp.c++/task-reduction-1.C
new file mode 100644
index 0000000..b3e228e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-1.C
@@ -0,0 +1,63 @@
+extern "C" void abort ();
+
+int as;
+int &a = as;
+long int bs = 1;
+long int &b = bs;
+
+void
+foo (int &c, long long int &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: d) in_reduction (+: c) \
+ in_reduction (+: a) in_reduction (*: b)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ }
+}
+
+int
+main ()
+{
+ int cs = 0;
+ int &c = cs;
+ long long int ds = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int &d = ds;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ int j;
+ a += 7;
+ b *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ foo (c, d);
+ }
+ c += 9;
+ d *= 3;
+ }
+ }
+#define THREEP4 (3LL * 3LL * 3LL * 3LL)
+ if (d != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+ }
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-10.C b/libgomp/testsuite/libgomp.c++/task-reduction-10.C
new file mode 100644
index 0000000..0eb94c1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-10.C
@@ -0,0 +1,125 @@
+extern "C" void abort ();
+
+struct S { S (); S (long long int, int); ~S (); static int cnt1, cnt2, cnt3; long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as = { 0LL, 7 };
+S &a = as;
+S bs (1LL, 5);
+S &b = bs;
+
+void
+foo (S &c, S &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: c) in_reduction (*: b, d) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S cs = { 0LL, 7 };
+ S &c = cs;
+ S ds (1LL, 5);
+ #pragma omp parallel if (0)
+ {
+ S &d = ds;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b, d)
+ {
+ #pragma omp for
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo (c, d);
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP7 (3LL * 3LL * 3LL * 3LL * 3LL * 3LL * 3LL)
+ if (d.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || d.t != 5)
+ abort ();
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-11.C b/libgomp/testsuite/libgomp.c++/task-reduction-11.C
new file mode 100644
index 0000000..542bdd6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-11.C
@@ -0,0 +1,237 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+
+template <typename T>
+void
+foo (T &n, T *&c, long long int *&d, T (&m)[3], T *&r, T (&o)[4], T *&p, T (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+template <typename T>
+void
+test (T &n)
+{
+ T cs[2] = { 0, 0 };
+ T (&c)[2] = cs;
+ T ps[3] = { 0, 1, 4 };
+ T (&p)[3] = ps;
+ T qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ T (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ T ms[3] = { 5, 0, 5 };
+ T os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ T (&m)[3] = ms;
+ T rs[5] = { 6, 7, 0, 0, 9 };
+ T (&r)[5] = rs;
+ T (&o)[4] = os;
+ #pragma omp parallel reduction (task,+: a, c) reduction (task,*: b[2 * n:3 * n], d) \
+ reduction (task,+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task,+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task,*: t[2:2][:], s[1:n + 1])
+ {
+ #pragma omp for
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ T *cp = c;
+ long long int *dp = d;
+ T *rp = r;
+ T *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-12.C b/libgomp/testsuite/libgomp.c++/task-reduction-12.C
new file mode 100644
index 0000000..02c1a78
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-12.C
@@ -0,0 +1,321 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+template <int N>
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <int N>
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel num_threads (1) if (0)
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1])
+ {
+ #pragma omp for
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo<N> (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test<0> (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-13.C b/libgomp/testsuite/libgomp.c++/task-reduction-13.C
new file mode 100644
index 0000000..3d0165d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-13.C
@@ -0,0 +1,342 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as[2] = { { 0, 7 }, { 0, 7 } };
+S (&a)[2] = as;
+S bs[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S (&b)[7] = bs;
+S es[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S (&e)[3] = es;
+S fs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S (&f)[5] = fs;
+S gs[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S (&g)[4] = gs;
+S hs[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S (&h)[3] = hs;
+S ks[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S (&k)[4][2] = ks;
+S *ss;
+S *&s = ss;
+S (*ts)[2];
+S (*&t)[2] = ts;
+
+template <typename S, typename T>
+void
+foo (T &n, S *&c, S *&d, S (&m)[3], S *&r, S (&o)[4], S *&p, S (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <typename S, typename T>
+void
+test (T &n)
+{
+ S cs[2] = { { 0, 7 }, { 0, 7 } };
+ S (&c)[2] = cs;
+ S ps[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S (&p)[3] = ps;
+ S qs[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S (&q)[4][2] = qs;
+ S sb[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tb[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ S ms[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S os[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ S ds[] = { { 1, 5 }, { 1, 5 } };
+ S (&d)[2] = ds;
+ S (&m)[3] = ms;
+ S rs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S (&r)[5] = rs;
+ S (&o)[4] = os;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1])
+ {
+ #pragma omp for
+ for (T i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ S *cp = c;
+ S *dp = d;
+ S *rp = r;
+ S *pp = p;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || sb[0].s != 5
+ || sb[1].s != 1LL << (16 + 4)
+ || sb[2].s != 1LL << 8
+ || sb[3].s != 6
+ || tb[0][0].s != 9 || tb[0][1].s != 10 || tb[1][0].s != 11 || tb[1][1].s != 12
+ || tb[2][0].s != 1LL << (16 + 8)
+ || tb[2][1].s != 1LL << 4
+ || tb[3][0].s != 1LL << 8
+ || tb[3][1].s != 1LL << (16 + 4)
+ || tb[4][0].s != 13 || tb[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ int n = 1;
+ test<S, int> (n);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-14.C b/libgomp/testsuite/libgomp.c++/task-reduction-14.C
new file mode 100644
index 0000000..3f4e79b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-14.C
@@ -0,0 +1,72 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct A { A (); ~A (); A (const A &); static int cnt1, cnt2, cnt3; int a; };
+int A::cnt1;
+int A::cnt2;
+int A::cnt3;
+A::A () : a (0)
+{
+ #pragma omp atomic
+ cnt1++;
+}
+A::A (const A &x) : a (x.a)
+{
+ #pragma omp atomic
+ cnt2++;
+}
+A::~A ()
+{
+ #pragma omp atomic
+ cnt3++;
+}
+#pragma omp declare reduction (+: A: omp_out.a += omp_in.a)
+
+void
+foo (int x)
+{
+ A a, b[2];
+ int d = 1;
+ long int e[2] = { 1L, 1L };
+ int c = 0;
+ #pragma omp parallel
+ {
+ if (x && omp_get_thread_num () == 0)
+ {
+ for (int i = 0; i < 10000000; ++i)
+ asm volatile ("");
+ c = 1;
+ #pragma omp cancel parallel
+ }
+ #pragma omp for reduction (task, +: a, b) reduction (task, *: d, e)
+ for (int i = 0; i < 64; i++)
+ #pragma omp task in_reduction (+: a, b) in_reduction (*: d, e)
+ {
+ a.a++;
+ b[0].a += 2;
+ b[1].a += 3;
+ d *= ((i & 7) == 0) + 1;
+ e[0] *= ((i & 7) == 3) + 1;
+ e[1] *= ((i & 3) == 2) + 1;
+ }
+ if (x && omp_get_cancellation ())
+ abort ();
+ }
+ if (!c)
+ {
+ if (a.a != 64 || b[0].a != 128 || b[1].a != 192)
+ abort ();
+ if (d != 256 || e[0] != 256L || e[1] != 65536L)
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int c1 = A::cnt1, c2 = A::cnt2, c3 = A::cnt3;
+ volatile int zero = 0;
+ foo (zero);
+ if (A::cnt1 + A::cnt2 - c1 - c2 != A::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-15.C b/libgomp/testsuite/libgomp.c++/task-reduction-15.C
new file mode 100644
index 0000000..8a01e6b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-15.C
@@ -0,0 +1,75 @@
+extern "C" void abort ();
+
+int as;
+int &a = as;
+long int bs = 1;
+long int &b = bs;
+
+template <typename T, typename U>
+void
+foo (T &c, U &d)
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: d) in_reduction (+: c) \
+ in_reduction (+: a) in_reduction (*: b)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ }
+}
+
+template <typename T, typename U>
+void
+bar ()
+{
+ T cs = 0;
+ T &c = cs;
+ U ds = 1;
+ #pragma omp parallel if (0)
+ {
+ U &d = ds;
+ #pragma omp parallel
+ {
+ T i;
+ #pragma omp for reduction (task, +: a, c) reduction (task, *: b, d)
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ T j;
+ a += 7;
+ b *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ foo (c, d);
+ }
+ c += 9;
+ d *= 3;
+ }
+#define THREEP4 (3LL * 3LL * 3LL * 3LL)
+ if (d != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+ }
+ }
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+ if (ds != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+}
+
+int
+main ()
+{
+ bar<int, long long int> ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-16.C b/libgomp/testsuite/libgomp.c++/task-reduction-16.C
new file mode 100644
index 0000000..5835edc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-16.C
@@ -0,0 +1,130 @@
+extern "C" void abort ();
+
+struct S { S (); S (long long int, int); ~S (); static int cnt1, cnt2, cnt3; long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as = { 0LL, 7 };
+S &a = as;
+S bs (1LL, 5);
+S &b = bs;
+
+void
+foo (S &c, S &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: c) in_reduction (*: b, d) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S cs = { 0LL, 7 };
+ S &c = cs;
+ S ds (1LL, 5);
+ #pragma omp parallel if (0)
+ {
+ S &d = ds;
+ #pragma omp parallel shared (a, b, c, d)
+ {
+ #pragma omp for schedule (static, 1) reduction (task, +: a, c) reduction (task, *: b, d)
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo (c, d);
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+#define THREEP7 (3LL * 3LL * 3LL * 3LL * 3LL * 3LL * 3LL)
+ if (d.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || d.t != 5)
+ abort ();
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+ }
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+ if (ds.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || ds.t != 5)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-17.C b/libgomp/testsuite/libgomp.c++/task-reduction-17.C
new file mode 100644
index 0000000..c00c8e4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-17.C
@@ -0,0 +1,300 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+
+template <typename T>
+void
+foo (T &n, T *&c, long long int *&d, T (&m)[3], T *&r, T (&o)[4], T *&p, T (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+template <typename T, typename I>
+void
+test (T &n, I x, I y)
+{
+ T cs[2] = { 0, 0 };
+ T (&c)[2] = cs;
+ T ps[3] = { 0, 1, 4 };
+ T (&p)[3] = ps;
+ T qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ T (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ T ms[3] = { 5, 0, 5 };
+ T os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ T (&m)[3] = ms;
+ T rs[5] = { 6, 7, 0, 0, 9 };
+ T (&r)[5] = rs;
+ T (&o)[4] = os;
+ #pragma omp parallel
+ {
+ #pragma omp for reduction (task,+: a, c) reduction (task,*: b[2 * n:3 * n], d) \
+ reduction (task,+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task,+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task,*: t[2:2][:], s[1:n + 1]) schedule (dynamic)
+ for (I i = x; i != y; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ T *cp = c;
+ long long int *dp = d;
+ T *rp = r;
+ T *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n, 0ULL, 4ULL);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-18.C b/libgomp/testsuite/libgomp.c++/task-reduction-18.C
new file mode 100644
index 0000000..99c0e37
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-18.C
@@ -0,0 +1,325 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+template <int N>
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <int N>
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel num_threads (1) if (0)
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ volatile unsigned long long x = 0;
+ volatile unsigned long long y = 4;
+ volatile unsigned long long z = 1;
+ #pragma omp parallel
+ {
+ #pragma omp for reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1]) \
+ schedule (nonmonotonic: guided, 1)
+ for (unsigned long long i = x; i < y; i += z)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo<N> (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test<0> (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-19.C b/libgomp/testsuite/libgomp.c++/task-reduction-19.C
new file mode 100644
index 0000000..15945c5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-19.C
@@ -0,0 +1,343 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as[2] = { { 0, 7 }, { 0, 7 } };
+S (&a)[2] = as;
+S bs[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S (&b)[7] = bs;
+S es[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S (&e)[3] = es;
+S fs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S (&f)[5] = fs;
+S gs[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S (&g)[4] = gs;
+S hs[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S (&h)[3] = hs;
+S ks[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S (&k)[4][2] = ks;
+S *ss;
+S *&s = ss;
+S (*ts)[2];
+S (*&t)[2] = ts;
+
+template <typename S, typename T>
+void
+foo (T &n, S *&c, S *&d, S (&m)[3], S *&r, S (&o)[4], S *&p, S (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <typename S, typename T>
+void
+test (T &n)
+{
+ S cs[2] = { { 0, 7 }, { 0, 7 } };
+ S (&c)[2] = cs;
+ S ps[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S (&p)[3] = ps;
+ S qs[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S (&q)[4][2] = qs;
+ S sb[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tb[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ S ms[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S os[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ S ds[] = { { 1, 5 }, { 1, 5 } };
+ S (&d)[2] = ds;
+ S (&m)[3] = ms;
+ S rs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S (&r)[5] = rs;
+ S (&o)[4] = os;
+ #pragma omp parallel
+ {
+ #pragma omp for reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1]) \
+ schedule (monotonic: runtime)
+ for (T i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ S *cp = c;
+ S *dp = d;
+ S *rp = r;
+ S *pp = p;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || sb[0].s != 5
+ || sb[1].s != 1LL << (16 + 4)
+ || sb[2].s != 1LL << 8
+ || sb[3].s != 6
+ || tb[0][0].s != 9 || tb[0][1].s != 10 || tb[1][0].s != 11 || tb[1][1].s != 12
+ || tb[2][0].s != 1LL << (16 + 8)
+ || tb[2][1].s != 1LL << 4
+ || tb[3][0].s != 1LL << 8
+ || tb[3][1].s != 1LL << (16 + 4)
+ || tb[4][0].s != 13 || tb[4][1].s != 14)
+ abort ();
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ }
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ int n = 1;
+ test<S, int> (n);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-2.C b/libgomp/testsuite/libgomp.c++/task-reduction-2.C
new file mode 100644
index 0000000..75d2ee3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-2.C
@@ -0,0 +1,119 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a = { 0, 7 };
+S b (1, 5);
+
+void
+foo ()
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: b) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S c = { 0, 7 };
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S d (1, 5);
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo ();
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP4 (3L * 3L * 3L * 3L)
+ if (d.s != (THREEP4 * THREEP4 * THREEP4) || d.t != 5)
+ abort ();
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 12 * 9 || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-3.C b/libgomp/testsuite/libgomp.c++/task-reduction-3.C
new file mode 100644
index 0000000..a6eccf6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-3.C
@@ -0,0 +1,126 @@
+extern "C" void abort ();
+
+struct S { S (); S (long long int, int); ~S (); static int cnt1, cnt2, cnt3; long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as = { 0LL, 7 };
+S &a = as;
+S bs (1LL, 5);
+S &b = bs;
+
+void
+foo (S &c, S &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: c) in_reduction (*: b, d) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S cs = { 0LL, 7 };
+ S &c = cs;
+ S ds (1LL, 5);
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S &d = ds;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo (c, d);
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP7 (3LL * 3LL * 3LL * 3LL * 3LL * 3LL * 3LL)
+ if (d.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || d.t != 5)
+ abort ();
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-4.C b/libgomp/testsuite/libgomp.c++/task-reduction-4.C
new file mode 100644
index 0000000..1d4da79
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-4.C
@@ -0,0 +1,238 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+
+template <typename T>
+void
+foo (T &n, T *&c, long long int *&d, T (&m)[3], T *&r, T (&o)[4], T *&p, T (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+template <typename T>
+void
+test (T &n)
+{
+ T cs[2] = { 0, 0 };
+ T (&c)[2] = cs;
+ T ps[3] = { 0, 1, 4 };
+ T (&p)[3] = ps;
+ T qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ T (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ T ms[3] = { 5, 0, 5 };
+ T os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ T (&m)[3] = ms;
+ T rs[5] = { 6, 7, 0, 0, 9 };
+ T (&r)[5] = rs;
+ T (&o)[4] = os;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
+ task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ task_reduction (*: t[2:2][:], s[1:n + 1])
+ {
+ T i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ T *cp = c;
+ long long int *dp = d;
+ T *rp = r;
+ T *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-5.C b/libgomp/testsuite/libgomp.c++/task-reduction-5.C
new file mode 100644
index 0000000..59583f1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-5.C
@@ -0,0 +1,320 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
+ task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ task_reduction (*: t[2:2][:], s[1:n + 1])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-6.C b/libgomp/testsuite/libgomp.c++/task-reduction-6.C
new file mode 100644
index 0000000..d7f69da
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-6.C
@@ -0,0 +1,341 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as[2] = { { 0, 7 }, { 0, 7 } };
+S (&a)[2] = as;
+S bs[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S (&b)[7] = bs;
+S es[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S (&e)[3] = es;
+S fs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S (&f)[5] = fs;
+S gs[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S (&g)[4] = gs;
+S hs[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S (&h)[3] = hs;
+S ks[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S (&k)[4][2] = ks;
+S *ss;
+S *&s = ss;
+S (*ts)[2];
+S (*&t)[2] = ts;
+
+void
+foo (int &n, S *&c, S *&d, S (&m)[3], S *&r, S (&o)[4], S *&p, S (&q)[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+void
+test (int &n)
+{
+ S cs[2] = { { 0, 7 }, { 0, 7 } };
+ S (&c)[2] = cs;
+ S ps[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S (&p)[3] = ps;
+ S qs[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S (&q)[4][2] = qs;
+ S sb[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tb[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ S ms[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S os[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ s = sb;
+ t = tb;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S ds[] = { { 1, 5 }, { 1, 5 } };
+ S (&d)[2] = ds;
+ S (&m)[3] = ms;
+ S rs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S (&r)[5] = rs;
+ S (&o)[4] = os;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
+ task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ task_reduction (*: t[2:2][:], s[1:n + 1])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ S *cp = c;
+ S *dp = d;
+ S *rp = r;
+ S *pp = p;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || sb[0].s != 5
+ || sb[1].s != 1LL << (16 + 4)
+ || sb[2].s != 1LL << 8
+ || sb[3].s != 6
+ || tb[0][0].s != 9 || tb[0][1].s != 10 || tb[1][0].s != 11 || tb[1][1].s != 12
+ || tb[2][0].s != 1LL << (16 + 8)
+ || tb[2][1].s != 1LL << 4
+ || tb[3][0].s != 1LL << 8
+ || tb[3][1].s != 1LL << (16 + 4)
+ || tb[4][0].s != 13 || tb[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ int n = 1;
+ test (n);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-7.C b/libgomp/testsuite/libgomp.c++/task-reduction-7.C
new file mode 100644
index 0000000..2a4d82e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-7.C
@@ -0,0 +1,145 @@
+typedef __SIZE_TYPE__ size_t;
+extern "C" void abort ();
+
+void
+bar (int *a, int *b, int *c, int (*d)[2], int (*e)[4], int *f, int *g, size_t n)
+{
+ #pragma omp task in_reduction (*: a[:n], b[3:n], c[n:n], d[0][:n], e[0][1:n], f[:n], g[1:n])
+ {
+ a[0] *= 12;
+ a[1] *= 13;
+ b[3] *= 14;
+ b[4] *= 15;
+ c[n] *= 16;
+ c[n + 1] *= 17;
+ d[0][0] *= 18;
+ d[0][1] *= 19;
+ e[0][1] *= 20;
+ e[0][2] *= 21;
+ f[0] *= 22;
+ f[1] *= 23;
+ g[1] *= 24;
+ g[2] *= 25;
+ }
+}
+
+void
+foo (size_t n, void *x, void *y)
+{
+ int a[n], b[n + 3], c[2 * n];
+ int (*d)[n] = (int (*)[n]) x;
+ int (*e)[n * 2] = (int (*)[n * 2]) y;
+ int fb[n], gb[n * 2];
+ int (&f)[n] = fb;
+ int (&g)[n * 2] = gb;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ b[i + 3] = 1;
+ c[i + n] = 1;
+ d[0][i] = 1;
+ e[0][i + 1] = 1;
+ f[i] = 1;
+ g[i + 1] = 1;
+ }
+ #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, &f[0], &g[0], n);
+ #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ a[0] *= 2;
+ a[1] *= 3;
+ b[3] *= 4;
+ b[4] *= 5;
+ c[n] *= 6;
+ c[n + 1] *= 7;
+ d[0][0] *= 8;
+ d[0][1] *= 9;
+ e[0][1] *= 10;
+ e[0][2] *= 11;
+ f[0] *= 12;
+ f[1] *= 13;
+ g[1] *= 14;
+ g[2] *= 15;
+ }
+ n = 0;
+ }
+ if (a[0] != 24 || a[1] != 39 || b[3] != 56 || b[4] != 75)
+ abort ();
+ if (c[2] != 96 || c[3] != 119 || d[0][0] != 144 || d[0][1] != 171)
+ abort ();
+ if (e[0][1] != 200 || e[0][2] != 231 || f[0] != 264 || f[1] != 299)
+ abort ();
+ if (g[1] != 336 || g[2] != 375)
+ abort ();
+}
+
+void
+baz (size_t n, void *x, void *y)
+{
+ int a[n], b[n + 3], c[2 * n];
+ int (*d)[n] = (int (*)[n]) x;
+ int (*e)[n * 2] = (int (*)[n * 2]) y;
+ int fb[n], gb[n * 2];
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ b[i + 3] = 1;
+ c[i + n] = 1;
+ d[0][i] = 1;
+ e[0][i + 1] = 1;
+ fb[i] = 1;
+ gb[i + 1] = 1;
+ }
+ #pragma omp parallel num_threads(2)
+ #pragma omp master
+ {
+ int (&f)[n] = fb;
+ int (&g)[n * 2] = gb;
+ #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, &f[0], &g[0], n);
+ #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ a[0] *= 2;
+ a[1] *= 3;
+ b[3] *= 4;
+ b[4] *= 5;
+ c[n] *= 6;
+ c[n + 1] *= 7;
+ d[0][0] *= 8;
+ d[0][1] *= 9;
+ e[0][1] *= 10;
+ e[0][2] *= 11;
+ f[0] *= 12;
+ f[1] *= 13;
+ g[1] *= 14;
+ g[2] *= 15;
+ }
+ n = 0;
+ }
+ }
+ if (a[0] != 24 || a[1] != 39 || b[3] != 56 || b[4] != 75)
+ abort ();
+ if (c[2] != 96 || c[3] != 119 || d[0][0] != 144 || d[0][1] != 171)
+ abort ();
+ if (e[0][1] != 200 || e[0][2] != 231 || fb[0] != 264 || fb[1] != 299)
+ abort ();
+ if (gb[1] != 336 || gb[2] != 375)
+ abort ();
+}
+
+int
+main ()
+{
+ int d[2], e[4];
+ volatile int two;
+ two = 2;
+ #pragma omp parallel num_threads (2)
+ #pragma omp master
+ foo (two, (void *) d, (void *) e);
+ baz (two, (void *) d, (void *) e);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-8.C b/libgomp/testsuite/libgomp.c++/task-reduction-8.C
new file mode 100644
index 0000000..26737a3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-8.C
@@ -0,0 +1,70 @@
+extern "C" void abort ();
+
+int as;
+int &a = as;
+long int bs = 1;
+long int &b = bs;
+
+template <typename T, typename U>
+void
+foo (T &c, U &d)
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: d) in_reduction (+: c) \
+ in_reduction (+: a) in_reduction (*: b)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ }
+}
+
+template <typename T, typename U>
+void
+bar ()
+{
+ T cs = 0;
+ T &c = cs;
+ U ds = 1;
+ #pragma omp parallel if (0)
+ {
+ U &d = ds;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b, d)
+ {
+ T i;
+ #pragma omp for
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ T j;
+ a += 7;
+ b *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ foo (c, d);
+ }
+ c += 9;
+ d *= 3;
+ }
+ }
+#define THREEP4 (3LL * 3LL * 3LL * 3LL)
+ if (d != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+ }
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+}
+
+int
+main ()
+{
+ bar<int, long long int> ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-9.C b/libgomp/testsuite/libgomp.c++/task-reduction-9.C
new file mode 100644
index 0000000..068a7bb
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-9.C
@@ -0,0 +1,128 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a = { 0, 7 };
+S b (1, 5);
+
+void
+foo ()
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: b) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S c = { 0, 7 };
+ int t;
+ #pragma omp parallel num_threads (1)
+ {
+ S d (1, 5);
+ int r = 0;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b, d) \
+ reduction (+: r)
+ {
+ int i;
+ #pragma omp master
+ t = omp_get_num_threads ();
+ r++;
+ a.s += 3;
+ c.s += 4;
+ #pragma omp for
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo ();
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP4 (3L * 3L * 3L * 3L)
+ if (d.s != (THREEP4 * THREEP4 * THREEP4) || d.t != 5 || r != t)
+ abort ();
+ }
+ if (a.s != 28 * 7 + 3 * t || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 12 * 9 + 4 * t || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C
new file mode 100644
index 0000000..f7fb9ca
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C
@@ -0,0 +1,153 @@
+extern "C" void abort ();
+
+struct S { S (); S (unsigned long long int, int); ~S (); static int cnt1, cnt2, cnt3; unsigned long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (unsigned long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+rbar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+rbaz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) \
+ initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : rbaz (&omp_out, &omp_in)) \
+ initializer (rbar (&omp_priv, &omp_orig))
+
+S gs = { 0, 7 };
+S &g = gs;
+S hs (1, 5);
+S &h = hs;
+
+int
+foo (int *a, int &b)
+{
+ int xs = 0;
+ int &x = xs;
+ #pragma omp taskloop reduction (+:x) in_reduction (+:b)
+ for (int i = 0; i < 64; i++)
+ {
+ x += a[i];
+ b += a[i] * 2;
+ }
+ return x;
+}
+
+unsigned long long int
+bar (int *a, unsigned long long int &b)
+{
+ unsigned long long int xs = 1;
+ unsigned long long int &x = xs;
+ #pragma omp taskloop reduction (*:x) in_reduction (*:b)
+ for (int i = 0; i < 64; i++)
+ {
+ #pragma omp task in_reduction (*:x)
+ x *= a[i];
+ #pragma omp task in_reduction (*:b)
+ b *= (3 - a[i]);
+ }
+ return x;
+}
+
+void
+baz (int i, int *a, int *c)
+{
+ #pragma omp task in_reduction (*:h) in_reduction (+:g)
+ {
+ g.s += 7 * a[i];
+ h.s *= (3 - c[i]);
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ int i, j, a[64], b = 0, c[64];
+ unsigned long long int d = 1, e;
+ S ms (0, 7);
+ for (i = 0; i < 64; i++)
+ {
+ a[i] = 2 * i;
+ c[i] = 1 + ((i % 3) != 1);
+ }
+ #pragma omp parallel
+ #pragma omp master
+ {
+ S ns = { 1, 5 };
+ S &m = ms;
+ S &n = ns;
+ #pragma omp taskgroup task_reduction (+:b)
+ j = foo (a, b);
+ #pragma omp taskgroup task_reduction (*:d)
+ e = bar (c, d);
+ #pragma omp taskloop reduction (+: g, m) reduction (*: h, n)
+ for (i = 0; i < 64; ++i)
+ {
+ g.s += 3 * a[i];
+ h.s *= (3 - c[i]);
+ m.s += 4 * a[i];
+ n.s *= c[i];
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9)
+ || (m.t != 7 && m.t != 3) || (n.t != 5 && n.t != 9))
+ abort ();
+ baz (i, a, c);
+ }
+ if (n.s != (1ULL << 43) || n.t != 5)
+ abort ();
+ }
+ if (j != 63 * 64 || b != 63 * 64 * 2)
+ abort ();
+ if (e != (1ULL << 43) || d != (1ULL << 21))
+ abort ();
+ if (g.s != 63 * 64 * 10 || g.t != 7)
+ abort ();
+ if (h.s != (1ULL << 42) || h.t != 5)
+ abort ();
+ if (ms.s != 63 * 64 * 4 || ms.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C
new file mode 100644
index 0000000..f1de5da
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C
@@ -0,0 +1,253 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+struct U { U (); ~U () {}; U (const U &); int u[4]; };
+
+U::U
+()
+{
+ u[0] = 0; u[1] = 1; u[2] = 2; u[3] = 3;
+}
+
+U::U
+(const U &r)
+{
+ u[0] = r.u[0]; u[1] = r.u[1]; u[2] = r.u[2]; u[3] = r.u[3];
+}
+
+void
+foo (int &n, int *&c, long long int *&d, int (&m)[3], int *&r, int (&o)[4], int *&p, int (&q)[4][2])
+{
+ int i;
+ U u;
+ u.u[2] = 8;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:]) firstprivate (u) nogroup
+ for (i = 0; i < 2; i++)
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ if (u.u[2] != 8)
+ abort ();
+ }
+}
+
+void
+test (int &n)
+{
+ int cs[2] = { 0, 0 };
+ int (&c)[2] = cs;
+ int ps[3] = { 0, 1, 4 };
+ int (&p)[3] = ps;
+ int qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ int (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ int ms[3] = { 5, 0, 5 };
+ int os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ U u;
+ u.u[2] = 10;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ int (&m)[3] = ms;
+ int rs[5] = { 6, 7, 0, 0, 9 };
+ int (&r)[5] = rs;
+ int (&o)[4] = os;
+ int i;
+ #pragma omp taskloop reduction (+: a, c) reduction (*: b[2 * n:3 * n], d) \
+ reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (*: t[2:2][:], s[1:n + 1]) firstprivate (u)
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ if (u.u[2] != 10)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:]) firstprivate (u)
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ int *cp = c;
+ long long int *dp = d;
+ int *rp = r;
+ int *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ if (u.u[2] != 10)
+ abort ();
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C
new file mode 100644
index 0000000..0588e47
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C
@@ -0,0 +1,314 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:]) nogroup
+ for (i = 0; i < 2; i++)
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ int i;
+ #pragma omp taskloop reduction (+: a, c) reduction (*: b[2 * n:3 * n], d) \
+ reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (*: t[2:2][:], s[1:n + 1])
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ #pragma omp taskloop in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:]) nogroup
+ for (j = 0; j < 2; j++)
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C
new file mode 100644
index 0000000..41c7040
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C
@@ -0,0 +1,315 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+template <int N>
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ reduction (default, +: o[n:n*2], m[1], p[0]) in_reduction (+: k[1:2][:], f[2:2]) \
+ reduction (+: q[1:2][:], r[2:2]) in_reduction (+: g[n:n*2], e[1], h[0]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ for (i = 0; i < 2; i++)
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <typename T>
+void
+test (int n)
+{
+ T c[2] = { { 0, 7 }, { 0, 7 } };
+ T p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ T q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ T ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ T tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ T d[] = { { 1, 5 }, { 1, 5 } };
+ T m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ T r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ T o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ int i;
+ #pragma omp taskloop reduction (+: a, c) reduction (default, *: b[2 * n:3 * n], d) \
+ reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (*: t[2:2][:], s[1:n + 1])
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ #pragma omp taskloop in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:]) nogroup
+ for (j = 0; j < 2; j++)
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo<0> (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test<S> (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}