--- libgomp/testsuite/libgomp.c/cancel-for-2.c	(.../trunk)	(revision 265884)
+++ libgomp/testsuite/libgomp.c/cancel-for-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -20,7 +20,7 @@ foo (int *x)
     #pragma omp for
     for (i = 0; i < 1000; ++i)
       {
-	#pragma omp cancel for if (x[1])
+	#pragma omp cancel for if (cancel: x[1])
 	#pragma omp atomic
 	v++;
       }
@@ -34,7 +34,7 @@ foo (int *x)
     #pragma omp for
     for (i = 0; i < 1000; ++i)
       {
-	#pragma omp cancel for if (x[3])
+	#pragma omp cancel for if ( cancel : x[3])
 	#pragma omp atomic
 	v += 2;
       }
@@ -54,7 +54,7 @@ foo (int *x)
 	#pragma omp cancel for if (x[0])
 	abort ();
       }
-    #pragma omp cancel parallel if (omp_get_thread_num () == 2 && x[4])
+    #pragma omp cancel parallel if (cancel:omp_get_thread_num () == 2 && x[4])
     #pragma omp for
     for (i = 0; i < 1000; ++i)
       {
--- libgomp/testsuite/libgomp.c-c++-common/cancel-parallel-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/cancel-parallel-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+  int a[64];
+  #pragma omp parallel
+  {
+    #pragma omp barrier
+    if (omp_get_thread_num () == 0)
+      {
+	#pragma omp cancel parallel
+      }
+    #pragma omp for
+    for (int i = 0; i < 64; i++)
+      a[i] = i;
+    if (omp_get_cancellation ())
+      abort ();
+  }
+  #pragma omp parallel
+  {
+    #pragma omp barrier
+    if (omp_get_thread_num () == 0)
+      {
+	#pragma omp cancel parallel
+      }
+    #pragma omp taskgroup
+    {
+      #pragma omp for
+      for (int i = 0; i < 64; i++)
+	#pragma omp task
+	a[i] += i;
+      if (omp_get_cancellation ())
+	abort ();
+    }
+  }
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-3.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-3.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,68 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+  int a = 0, i;
+  #pragma omp parallel
+  #pragma omp taskgroup
+  {
+    #pragma omp task
+    {
+      #pragma omp cancel taskgroup
+      if (omp_get_cancellation ())
+	abort ();
+    }
+    #pragma omp taskwait
+    #pragma omp for reduction (task, +: a)
+    for (i = 0; i < 64; ++i)
+      {
+	a++;
+	#pragma omp task in_reduction (+: a)
+	{
+	  volatile int zero = 0;
+	  a += zero;
+	  if (omp_get_cancellation ())
+	    abort ();
+	}
+      }
+    if (a != 64)
+      abort ();
+    #pragma omp task
+    {
+      if (omp_get_cancellation ())
+	abort ();
+    }
+  }
+  a = 0;
+  #pragma omp parallel
+  #pragma omp taskgroup
+  {
+    #pragma omp taskwait
+    #pragma omp for reduction (task, +: a)
+    for (i = 0; i < 64; ++i)
+      {
+	a++;
+	#pragma omp task in_reduction (+: a)
+	{
+	  volatile int zero = 0;
+	  a += zero;
+	  #pragma omp cancel taskgroup
+	  if (omp_get_cancellation ())
+	    abort ();
+	}
+      }
+    if (a != 64)
+      abort ();
+    #pragma omp task
+    {
+      if (omp_get_cancellation ())
+	abort ();
+    }
+  }
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,115 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+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;
+
+int
+main ()
+{
+  int m;
+  beg = 60;
+  end = -4;
+  step = -4;
+  step2 = 4;
+  begu = -64U;
+  endu = -32U;
+  #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;
+  }
+  for (m = 0; m < 64; m++)
+    if (arr[m] != m + 15 || arr2[m] != (m < 32 ? 1365 : 85))
+      abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,63 @@
+volatile int v;
+
+__attribute__((noipa)) void
+foo (int *p, int i)
+{
+  #pragma omp task depend (out: p[0])
+  v++;
+  #pragma omp task depend (in: p[0])
+  v++;
+  #pragma omp task depend (inout: p[0])
+  v++;
+  #pragma omp task depend (mutexinoutset: p[0])
+  v++;
+  #pragma omp task depend (out: p[0]) depend (in: p[1])
+  v++;
+  #pragma omp task depend (in: p[0]) depend (inout: p[1])
+  v++;
+  #pragma omp task depend (inout: p[0]) depend (mutexinoutset: p[1])
+  v++;
+  #pragma omp task depend (mutexinoutset: p[0]) depend (out: p[1])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , out : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , in : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , inout : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , mutexinoutset : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , out : p[j]) depend (iterator (j=0:2) , in : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , in : p[j]) depend (iterator (j=0:2) , inout : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , inout : p[j]) depend (iterator (j=0:2) , mutexinoutset : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) , mutexinoutset : p[j]) depend (iterator (j=0:2) , out : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , out : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , in : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , inout : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , mutexinoutset : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , out : p[j]) depend (iterator (j=0:i) , in : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , in : p[j]) depend (iterator (j=0:i) , inout : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , inout : p[j]) depend (iterator (j=0:i) , mutexinoutset : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) , mutexinoutset : p[j]) depend (iterator (j=0:i) , out : p[j + 2])
+  v++;
+}
+
+int
+main ()
+{
+  int p[4];
+  foo (p, 2);
+  foo (p, -1);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,28 @@
+int
+main ()
+{
+  int a, b, c, d;
+  #pragma omp parallel num_threads (6)
+  #pragma omp single
+  {
+    #pragma omp task depend(out: c)
+      c = 1;
+    #pragma omp task depend(out: a)
+      a = 2;
+    #pragma omp task depend(out: b)
+      b = 3;
+    /* The above 3 tasks can be scheduled in any order.  */
+    #pragma omp task depend(in: a) depend(mutexinoutset: c)
+      c += a;
+    #pragma omp task depend(in: b) depend(mutexinoutset: c)
+      c += b;
+    /* The above 2 tasks are mutually exclusive and need to wait
+       for the first and second or first and third tasks respectively.  */
+    #pragma omp task depend(in: c)
+      d = c;
+    /* The above task needs to wait for the mutexinoutset tasks.  */
+  }
+  if (d != 6)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-2.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,59 @@
+int
+main ()
+{
+  int a, b, c = 0;
+  #pragma omp parallel num_threads(2)
+  {
+    #pragma omp barrier
+    #pragma omp single
+    {
+      #pragma omp task depend(out: a)
+      {
+	int i;
+	a = 0;
+	for (i = 0; i < 524288; ++i)
+	  {
+	    asm volatile ("" : "+g" (a));
+	    a++;
+	  }
+      }
+      #pragma omp task depend(out: b)
+      {
+	int i;
+	b = 0;
+	for (i = 0; i < 64; ++i)
+	  {
+	    asm volatile ("" : "+g" (b));
+	    b++;
+	  }
+      }
+      #pragma omp task depend(in: a) depend(mutexinoutset: c)
+      {
+	int i;
+	int d = c;
+	for (i = 0; i < 524288 + 64 - a; ++i)
+	  {
+	    asm volatile ("" : "+g" (d) : "g" (&a) : "memory");
+	    d++;
+	  }
+	asm volatile ("" : "+g" (d), "+g" (c));
+	c = d;
+      }
+      #pragma omp task depend(in: b) depend(mutexinoutset: c)
+      {
+	int i;
+	int d = c;
+	for (i = 0; i < 524288 + 64 - b; ++i)
+	  {
+	    asm volatile ("" : "+g" (d) : "g" (&b) : "memory");
+	    d++;
+	  }
+	asm volatile ("" : "+g" (d), "+g" (c));
+	c = d;
+      }
+    }
+  }
+  if (c != 524288 + 64)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/depobj-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/depobj-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,99 @@
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (void)
+{
+  int x = 1;
+  omp_depend_t d1, d2;
+  #pragma omp depobj (d1) depend(in: x)
+  #pragma omp depobj (d2) depend(in: x)
+  #pragma omp depobj (d2) 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) destroy
+  #pragma omp depobj (d1) destroy
+}
+
+void
+dep2 (void)
+{
+  #pragma omp parallel
+  #pragma omp single
+  {
+    int x = 1;
+    omp_depend_t d1, d2;
+    #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
+  }
+}
+
+void
+dep3 (void)
+{
+  omp_depend_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;
+
+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 ()
+{
+  dep ();
+  dep2 ();
+  dep3 ();
+  #pragma omp depobj (dd1) depend (inout: xx)
+  #pragma omp depobj (dd2) depend (in : xx)
+  antidep ();
+  #pragma omp depobj (dd2) destroy
+  #pragma omp depobj (dd1) destroy
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/display-affinity-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/display-affinity-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,91 @@
+/* { dg-set-target-env-var OMP_PROC_BIND "spread,close" } */
+/* { dg-set-target-env-var OMP_PLACES "cores" } */
+/* { dg-set-target-env-var OMP_NUM_THREADS "4" } */
+/* { dg-set-target-env-var OMP_AFFINITY_FORMAT "hello" } */
+
+#include <omp.h>
+#include <string.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+#define FMT "L:%0.5L%%%n>%32H<!%.33{host}!%.6P_%i_%0.18i_%0.7{ancestor_tnum} %18A"
+  char buf[] = FMT, hostname[256], buf2[512 + 32], *q;
+  size_t l, l2, l3;
+  char *r = getenv ("OMP_AFFINITY_FORMAT");
+  if (r && strcmp (r, "hello") == 0)
+    {
+      if (omp_get_affinity_format (NULL, 0) != 5)
+	abort ();
+      if (omp_get_affinity_format (buf2, 3) != 5
+	  || strcmp (buf2, "he") != 0)
+	abort ();
+      if (omp_get_affinity_format (buf2, 6) != 5
+	  || strcmp (buf2, "hello") != 0)
+	abort ();
+    }
+  omp_set_affinity_format (buf);
+  memset (buf, '^', sizeof (buf));
+  if (omp_get_affinity_format (NULL, 0) != sizeof (buf) - 1)
+    abort ();
+  if (omp_get_affinity_format (buf, 3) != sizeof (buf) - 1
+      || buf[0] != FMT[0] || buf[1] != FMT[1] || buf[2] != '\0')
+    abort ();
+  memset (buf, ' ', sizeof (buf));
+  if (omp_get_affinity_format (buf, sizeof (buf) - 1) != sizeof (buf) - 1
+      || strncmp (buf, FMT, sizeof (buf) - 2) != 0
+      || buf[sizeof (buf) - 2] != '\0')
+    abort ();
+  memset (buf, '-', sizeof (buf));
+  if (omp_get_affinity_format (buf, sizeof (buf)) != sizeof (buf) - 1
+      || strcmp (buf, FMT) != 0)
+    abort ();
+  memset (buf, '0', sizeof (buf));
+  omp_display_affinity (NULL);
+  omp_display_affinity ("");
+  omp_display_affinity ("%%%0.9N");
+  omp_set_affinity_format ("%{host}");
+  l = omp_capture_affinity (hostname, sizeof hostname, NULL);
+  if (l < sizeof (hostname))
+    {
+      if (strlen (hostname) != l)
+	abort ();
+      l2 = omp_capture_affinity (NULL, 0,
+				 "%0.5{nesting_level}%%%32{host}|||%.33H"
+				 "%0.7a%3N!%N!");
+      if (l2 != (5 + 1 + (l > 32 ? l : 32) + 3 + (l > 33 ? l : 33)
+		 + 7 + 3 + 1 + 1 + 1))
+	abort ();
+      omp_set_affinity_format ("%.5L%%%32H|||%.33{host}%0.7{ancestor_tnum}"
+			       "%3{num_threads}!%{num_threads}!");
+      l3 = omp_capture_affinity (buf2, sizeof buf2, "");
+      if (l3 != l2)
+	abort ();
+      if (memcmp (buf2, "    0%", 5 + 1) != 0)
+	abort ();
+      q = buf2 + 6;
+      if (memcmp (q, hostname, l) != 0)
+	abort ();
+      q += l;
+      if (l < 32)
+	for (l3 = 32 - l; l3; l3--)
+	  if (*q++ != ' ')
+	    abort ();
+      if (memcmp (q, "|||", 3) != 0)
+	abort ();
+      q += 3;
+      if (l < 33)
+	for (l3 = 33 - l; l3; l3--)
+	  if (*q++ != ' ')
+	    abort ();
+      if (memcmp (q, hostname, l) != 0)
+	abort ();
+      q += l;
+      if (strcmp (q, "-0000011  !1!") != 0)
+	abort ();
+    }
+  #pragma omp parallel num_threads (4) proc_bind(spread)
+  omp_display_affinity ("%0.2a!%n!%.4L!%N;%.2t;%0.2T;%{team_num};%{num_teams};%A");
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/for-10.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-10.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-4.c"
--- libgomp/testsuite/libgomp.c-c++-common/for-11.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-11.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-5.c"
--- libgomp/testsuite/libgomp.c-c++-common/for-12.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-12.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-6.c"
--- libgomp/testsuite/libgomp.c-c++-common/for-13.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-13.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,99 @@
+unsigned short a[256];
+
+__attribute__((noinline, noclone)) void
+bar (void *x, unsigned short z)
+{
+  unsigned short *y = (unsigned short *) x;
+  if (y < &a[5] || y > &a[222] || y == &a[124])
+    __builtin_abort ();
+  *y += z;
+}
+
+__attribute__((noinline, noclone)) void
+foo (void *qx, void *rx, void *sx, int n)
+{
+  unsigned short (*q)[n], (*r)[n], (*s)[n], (*p)[n];
+  q = (typeof (q)) qx;
+  r = (typeof (r)) rx;
+  s = (typeof (s)) sx;
+  #pragma omp for
+  for (p = q; p != r; p++)
+    bar (p, 1);
+  #pragma omp for
+  for (p = s; p != r; p--)
+    bar (p, 2);
+  #pragma omp for
+  for (p = q; p != r; p = p + 1)
+    bar (p, 4);
+  #pragma omp for
+  for (p = s; p != r; p = p - 1)
+    bar (p, 8);
+  #pragma omp for
+  for (p = q; p != r; p = 1 + p)
+    bar (p, 16);
+  #pragma omp for
+  for (p = s; p != r; p = -1 + p)
+    bar (p, 32);
+  #pragma omp for
+  for (p = q; p != r; p += 1)
+    bar (p, 64);
+  #pragma omp for
+  for (p = s; p != r; p -= 1)
+    bar (p, 128);
+}
+
+__attribute__((noinline, noclone)) void
+baz (void *qx, void *rx, void *sx, int n)
+{
+  unsigned short (*q)[n], (*r)[n], (*s)[n], (*p)[n];
+  q = (typeof (q)) qx;
+  r = (typeof (r)) rx;
+  s = (typeof (s)) sx;
+  #pragma omp for
+  for (p = q; p < r; p++)
+    bar (p, 256);
+  #pragma omp for
+  for (p = s; p > r; p--)
+    bar (p, 512);
+  #pragma omp for
+  for (p = q; p < r; p = p + 1)
+    bar (p, 1024);
+  #pragma omp for
+  for (p = s; p > r; p = p - 1)
+    bar (p, 2048);
+  #pragma omp for
+  for (p = q; p < r; p = 1 + p)
+    bar (p, 4096);
+  #pragma omp for
+  for (p = s; p > r; p = -1 + p)
+    bar (p, 8192);
+  #pragma omp for
+  for (p = q; p < r; p += 1)
+    bar (p, 16384);
+  #pragma omp for
+  for (p = s; p > r; p -= 1)
+    bar (p, 32768U);
+}
+
+int
+main ()
+{
+  int i;
+  volatile int j = 7;
+#pragma omp parallel
+  {
+    foo (&a[5 + (j - 7)], &a[124 + (j - 7)], &a[222 + (j - 7)], j);
+    baz (&a[5 + (j - 7)], &a[124 + (j - 7)], &a[222 + (j - 7)], j);
+  }
+  for (i = 0; i < 256; i++)
+    if (i < 5 || i > 222 || i == 124 || ((i - 5) % 7) != 0)
+      {
+	if (a[i])
+	  __builtin_abort ();
+      }
+    else if (i < 124 && a[i] != 1 + 4 + 16 + 64 + 256 + 1024 + 4096 + 16384)
+      __builtin_abort ();
+    else if (i > 124 && a[i] != 2 + 8 + 32 + 128 + 512 + 2048 + 8192 + 32768U)
+      __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/for-14.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-14.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,110 @@
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F distribute
+#define G d
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute
+#define G d_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute parallel for
+#define G dpf
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for dist_schedule(static, 128)
+#define G dpf_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd
+#define G dpfs
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd dist_schedule(static, 128)
+#define G dpfs_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+  int err = 0;
+  #pragma omp teams reduction(|:err)
+    {
+      err |= test_d_normal ();
+      err |= test_d_ds128_normal ();
+      err |= test_ds_normal ();
+      err |= test_ds_ds128_normal ();
+      err |= test_dpf_static ();
+      err |= test_dpf_static32 ();
+      err |= test_dpf_auto ();
+      err |= test_dpf_guided32 ();
+      err |= test_dpf_runtime ();
+      err |= test_dpf_ds128_static ();
+      err |= test_dpf_ds128_static32 ();
+      err |= test_dpf_ds128_auto ();
+      err |= test_dpf_ds128_guided32 ();
+      err |= test_dpf_ds128_runtime ();
+      err |= test_dpfs_static ();
+      err |= test_dpfs_static32 ();
+      err |= test_dpfs_auto ();
+      err |= test_dpfs_guided32 ();
+      err |= test_dpfs_runtime ();
+      err |= test_dpfs_ds128_static ();
+      err |= test_dpfs_ds128_static32 ();
+      err |= test_dpfs_ds128_auto ();
+      err |= test_dpfs_ds128_guided32 ();
+      err |= test_dpfs_ds128_runtime ();
+    }
+  if (err)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/for-15.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-15.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,115 @@
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F for
+#define G f
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute
+#define G td
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute
+#define G td_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute simd
+#define G tds
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute simd
+#define G tds_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute parallel for
+#define G tdpf
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F teams distribute parallel for dist_schedule(static, 128)
+#define G tdpf_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F teams distribute parallel for simd
+#define G tdpfs
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F teams distribute parallel for simd dist_schedule(static, 128)
+#define G tdpfs_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+  if (test_td_normal ()
+      || test_td_ds128_normal ()
+      || test_tds_normal ()
+      || test_tds_ds128_normal ()
+      || test_tdpf_static ()
+      || test_tdpf_static32 ()
+      || test_tdpf_auto ()
+      || test_tdpf_guided32 ()
+      || test_tdpf_runtime ()
+      || test_tdpf_ds128_static ()
+      || test_tdpf_ds128_static32 ()
+      || test_tdpf_ds128_auto ()
+      || test_tdpf_ds128_guided32 ()
+      || test_tdpf_ds128_runtime ()
+      || test_tdpfs_static ()
+      || test_tdpfs_static32 ()
+      || test_tdpfs_auto ()
+      || test_tdpfs_guided32 ()
+      || test_tdpfs_runtime ()
+      || test_tdpfs_ds128_static ()
+      || test_tdpfs_ds128_static32 ()
+      || test_tdpfs_ds128_auto ()
+      || test_tdpfs_ds128_guided32 ()
+      || test_tdpfs_ds128_runtime ())
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/for-2.h	(.../trunk)	(revision 265884)
+++ libgomp/testsuite/libgomp.c-c++-common/for-2.h	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -21,6 +21,7 @@ noreturn (void)
 #define OMPFROM(v) do {} while (0)
 #endif
 
+#ifndef CONDNE
 __attribute__((noinline, noclone)) void
 N(f0) (void)
 {
@@ -311,3 +312,292 @@ N(test) (void)
 	  return 1;
   return 0;
 }
+
+#else
+
+__attribute__((noinline, noclone)) void
+N(f20) (void)
+{
+  int i;
+  OMPTGT
+#pragma omp F S
+  for (i = 0; i != 1500; i++)
+    a[i] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f21) (void)
+{
+  OMPTGT
+#pragma omp F S
+  for (unsigned int i = __INT_MAX__; i < 1500U + __INT_MAX__; i += 2 - 1)
+    a[(i - __INT_MAX__)] -= 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f22) (void)
+{
+  unsigned long long i;
+  OMPTGT
+#pragma omp F S
+  for (i = __LONG_LONG_MAX__ + 1500ULL - 27;
+       i != __LONG_LONG_MAX__ - 27ULL; i -= 3 - 2)
+    a[i + 26LL - __LONG_LONG_MAX__] -= 4;
+}
+
+__attribute__((noinline, noclone)) void
+N(f23) (long long n1, long long n2)
+{
+  OMPTGT
+#pragma omp F S
+  for (long long i = n1 + 23; i != n2 - 25; --i)
+    a[i + 48] += 7;
+}
+
+__attribute__((noinline, noclone)) void
+N(f24) (void)
+{
+  unsigned int i;
+  OMPTGT
+#pragma omp F S
+  for (i = 30; i != 30; i += 1)
+    a[i] += 10;
+}
+
+__attribute__((noinline, noclone)) void
+N(f25) (int n11, int n12, int n21, int n22, int n31, int n32,
+	int s2)
+{
+  SC int v1, v2, v3;
+  OMPTGT
+#pragma omp F S collapse(3)
+  for (v1 = n11; v1 != n12; v1 += 17 - 19 + 3)
+    for (v2 = n21; v2 < n22; v2 += s2)
+      for (v3 = n31; v3 != n32; ++v3)
+	b[v1][v2][v3] += 2.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f26) (int n11, int n12, int n21, int n22, long long n31, long long n32,
+	int s2)
+{
+  SC int v1, v2;
+  SC long long v3;
+  OMPTGT
+#pragma omp F S collapse(3)
+  for (v1 = n11; v1 != n12; v1 += -1)
+    for (v2 = n21; v2 > n22; v2 += s2)
+      for (v3 = n31; v3 != n32; v3 --)
+	b[v1][v2 / 2][v3] -= 4.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f27) (void)
+{
+  SC unsigned int v1, v3;
+  SC unsigned long long v2;
+  OMPTGT
+#pragma omp F S collapse(3)
+  for (v1 = 0; v1 < 20; v1 += 2)
+    for (v2 = __LONG_LONG_MAX__ + 11ULL;
+	 v2 != __LONG_LONG_MAX__ - 4ULL; -- v2)
+      for (v3 = 10; v3 != 0; v3--)
+	b[v1 >> 1][v2 - __LONG_LONG_MAX__ + 3][v3 - 1] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f28) (void)
+{
+  SC long long v1, v2, v3;
+  OMPTGT
+#pragma omp F S collapse(3)
+  for (v1 = 0; v1 != 20; v1 -= 17 - 18)
+    for (v2 = 30; v2 < 20; v2++)
+      for (v3 = 10; v3 < 0; v3--)
+	b[v1][v2][v3] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f29) (void)
+{
+  int i;
+  OMPTGT
+#pragma omp F S
+  for (i = 20; i != 20; i++)
+    {
+      a[i] += 2;
+      noreturn ();
+      a[i] -= 4;
+    }
+}
+
+__attribute__((noinline, noclone)) void
+N(f30) (void)
+{
+  SC int i;
+  OMPTGT
+#pragma omp F S collapse(3)
+  for (i = 0; i != 10; i++)
+    for (int j = 10; j < 8; j++)
+      for (long k = -10; k != 10; k++)
+	{
+	  b[i][j][k] += 4;
+	  noreturn ();
+	  b[i][j][k] -= 8;
+	}
+}
+
+__attribute__((noinline, noclone)) void
+N(f31) (int n)
+{
+  int i;
+  OMPTGT
+#pragma omp F S
+  for (i = 20; i != n; i++)
+    {
+      a[i] += 8;
+      noreturn ();
+      a[i] -= 16;
+    }
+}
+
+__attribute__((noinline, noclone)) void
+N(f32) (int n)
+{
+  SC int i;
+  OMPTGT
+#pragma omp F S collapse(3)
+  for (i = 0; i != 10; i++)
+    for (int j = n; j != 12; j++)
+      for (long k = -10; k != 10; k++)
+	{
+	  b[i][j][k] += 16;
+	  noreturn ();
+	  b[i][j][k] -= 32;
+	}
+}
+
+__attribute__((noinline, noclone)) void
+N(f33) (void)
+{
+  int *i;
+  OMPTGT
+#pragma omp F S
+  for (i = a; i != &a[1500]; i++)
+    i[0] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f34) (void)
+{
+  SC float *i;
+  OMPTGT
+#pragma omp F S collapse(3)
+  for (i = &b[0][0][0]; i != &b[0][0][10]; i++)
+    for (float *j = &b[0][15][0]; j > &b[0][0][0]; j -= 10)
+      for (float *k = &b[0][0][10]; k != &b[0][0][0]; --k)
+	b[i - &b[0][0][0]][(j - &b[0][0][0]) / 10 - 1][(k - &b[0][0][0]) - 1]
+	  -= 3.5;
+}
+
+__attribute__((noinline, noclone)) int
+N(test) (void)
+{
+  int i, j, k;
+  for (i = 0; i < 1500; i++)
+    a[i] = i - 25;
+  OMPTO (a);
+  N(f20) ();
+  OMPFROM (a);
+  for (i = 0; i < 1500; i++)
+    if (a[i] != i - 23)
+      return 1;
+  N(f21) ();
+  OMPFROM (a);
+  for (i = 0; i < 1500; i++)
+    if (a[i] != i - 25)
+      return 1;
+  N(f22) ();
+  OMPFROM (a);
+  for (i = 0; i < 1500; i++)
+    if (a[i] != i - 29)
+      return 1;
+  N(f23) (1500LL - 1 - 23 - 48, -1LL + 25 - 48);
+  OMPFROM (a);
+  for (i = 0; i < 1500; i++)
+    if (a[i] != i - 22)
+      return 1;
+  N(f24) ();
+  OMPFROM (a);
+  for (i = 0; i < 1500; i++)
+    if (a[i] != i - 22)
+      return 1;
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	b[i][j][k] = i - 2.5 + 1.5 * j - 1.5 * k;
+  OMPTO (b);
+  N(f25) (0, 10, 0, 15, 0, 10, 1);
+  OMPFROM (b);
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+	  return 1;
+  N(f25) (0, 10, 30, 15, 0, 10, 5);
+  OMPFROM (b);
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+	  return 1;
+  N(f26) (9, -1, 29, 0, 9, -1, -2);
+  OMPFROM (b);
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	if (b[i][j][k] != i - 4.5 + 1.5 * j - 1.5 * k)
+	  return 1;
+  N(f27) ();
+  OMPFROM (b);
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+	  return 1;
+  N(f28) ();
+  OMPFROM (b);
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+	  return 1;
+  N(f29) ();
+  N(f30) ();
+  N(f31) (20);
+  N(f32) (12);
+  OMPFROM (a);
+  OMPFROM (b);
+  for (i = 0; i < 1500; i++)
+    if (a[i] != i - 22)
+      return 1;
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+	  return 1;
+  N(f33) ();
+  N(f34) ();
+  OMPFROM (a);
+  OMPFROM (b);
+  for (i = 0; i < 1500; i++)
+    if (a[i] != i - 20)
+      return 1;
+  for (i = 0; i < 10; i++)
+    for (j = 0; j < 15; j++)
+      for (k = 0; k < 10; k++)
+	if (b[i][j][k] != i - 2.5 + 1.5 * j - 1.5 * k)
+	  return 1;
+  return 0;
+}
+#endif
--- libgomp/testsuite/libgomp.c-c++-common/for-7.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-7.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-1.c"
--- libgomp/testsuite/libgomp.c-c++-common/for-8.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-8.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-2.c"
--- libgomp/testsuite/libgomp.c-c++-common/for-9.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/for-9.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-3.c"
--- libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+#define N 64
+
+int
+main ()
+{
+  int p, *q, i, l;
+  int a[N];
+  q = a;
+  #pragma omp parallel master num_threads(4) private (p) shared(a)
+  {
+    int i;
+    p = omp_get_thread_num ();
+    if (p != 0)
+      abort ();
+    #pragma omp taskloop nogroup
+    for (i = 0; i < N; ++i)
+      {
+	if (omp_get_thread_num () >= 4)
+	  abort ();
+	a[i] = i;
+      }
+  }
+  #pragma omp parallel num_threads(4)
+  {
+    #pragma omp master taskloop lastprivate (i, l) firstprivate (q)
+    for (i = 0; i != N; i = i + 1)
+      l = q[i];
+  }
+  if (i != N || l != N - 1)
+    abort ();
+  #pragma omp parallel master taskloop num_threads(4) \
+		       lastprivate (i, l) firstprivate (q)
+  for (i = 0; i < N - 5; i += 2)
+    if (q[i] != i)
+      abort ();
+    else
+      l = q[i];
+  if (i != N - 4 || l != N - 6)
+    abort ();
+  #pragma omp parallel master taskloop simd num_threads(4)
+  for (i = 0; i < N; i++)
+    a[i] = 2 * a[i];
+  if (i != N)
+    abort ();
+  #pragma omp parallel num_threads(4)
+  {
+    int j;
+    #pragma omp master taskloop simd collapse(2)
+    for (i = 0; i < 2; i += 2)
+      for (j = 0; j < N; j++)
+	a[j] = a[j] + 1;
+  }
+  for (i = 0; i < N; i++)
+    if (a[i] != 2 * i + 1)
+      abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/pause-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/pause-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,23 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int a[64];
+
+int
+main ()
+{
+  int i;
+  #pragma omp parallel for
+  for (i = 0; i < 64; i++)
+    a[i] = i;
+  omp_pause_resource (omp_pause_soft, omp_get_initial_device ());
+  #pragma omp parallel for
+  for (i = 0; i < 64; i++)
+    a[i] += i;
+  omp_pause_resource_all (omp_pause_hard);
+  #pragma omp parallel for
+  for (i = 0; i < 64; i++)
+    if (a[i] != 2 * i)
+      abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/pause-2.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/pause-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-require-effective-target tls_runtime } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+int t = 128;
+#pragma omp threadprivate (t)
+
+int
+main ()
+{
+  #pragma omp parallel
+  t = omp_get_thread_num () + 256;
+  #pragma omp parallel
+  if (t != omp_get_thread_num () + 256)
+    abort ();
+  omp_pause_resource (omp_pause_soft, omp_get_initial_device ());
+  /* This goes beyond what is required by the standard, we actually
+     check if the threads other than the initial one have been destroyed.  */
+  #pragma omp parallel
+  {
+    if (omp_get_thread_num () != 0 && t != 128)
+      abort ();
+    t = omp_get_thread_num () + 384;
+  }
+  #pragma omp parallel
+  if (t != omp_get_thread_num () + 384)
+    abort ();
+  omp_pause_resource_all (omp_pause_hard);
+  #pragma omp parallel
+  {
+    if (omp_get_thread_num () != 0 && t != 128)
+      abort ();
+    t = omp_get_thread_num () + 512;
+  }
+  #pragma omp parallel
+  if (t != omp_get_thread_num () + 512)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/pr66199-10.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/pr66199-10.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,60 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f1 (long a, long b)
+{
+  long d;
+  #pragma omp teams distribute parallel for simd default(none) firstprivate (a, b) shared(u, v, w)
+  for (d = a; d < b; d++)
+    u[d] = v[d] + w[d];
+  return d;
+}
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+  long d, e;
+  #pragma omp teams distribute parallel for simd default(none) firstprivate (a, b, c) shared(u, v, w) linear(d) lastprivate(e)
+  for (d = a; d < b; d++)
+    {
+      u[d] = v[d] + w[d];
+      e = c + d * 5;
+    }
+  return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams distribute parallel for simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) lastprivate(d1, d2) collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+__attribute__((noinline, noclone)) long
+f4 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams distribute parallel for simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+int
+main ()
+{
+  if (f1 (0, 1024) != 1024
+      || f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+      || f3 (0, 32, 0, 32) != 64
+      || f4 (0, 32, 0, 32) != 64)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/pr66199-11.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/pr66199-11.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,38 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+/* { dg-options "-O2" { target c } } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+  long d, e;
+  #pragma omp teams distribute parallel for default(none) firstprivate (a, b, c) shared(u, v, w) lastprivate(d, e)
+  for (d = a; d < b; d++)
+    {
+      u[d] = v[d] + w[d];
+      e = c + d * 5;
+    }
+  return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams distribute parallel for default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) lastprivate(d1, d2) collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+int
+main ()
+{
+  if (f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+      || f3 (0, 32, 0, 32) != 64)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/pr66199-12.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/pr66199-12.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,60 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f1 (long a, long b)
+{
+  long d;
+  #pragma omp teams distribute simd default(none) firstprivate (a, b) shared(u, v, w)
+  for (d = a; d < b; d++)
+    u[d] = v[d] + w[d];
+  return d;
+}
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+  long d, e;
+  #pragma omp teams distribute simd default(none) firstprivate (a, b, c) shared(u, v, w) linear(d) lastprivate(e)
+  for (d = a; d < b; d++)
+    {
+      u[d] = v[d] + w[d];
+      e = c + d * 5;
+    }
+  return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams distribute simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) lastprivate(d1, d2) collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+__attribute__((noinline, noclone)) long
+f4 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams distribute simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+int
+main ()
+{
+  if (f1 (0, 1024) != 1024
+      || f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+      || f3 (0, 32, 0, 32) != 64
+      || f4 (0, 32, 0, 32) != 64)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/pr66199-13.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/pr66199-13.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,64 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f1 (long a, long b)
+{
+  long d;
+  #pragma omp teams default(none) shared(a, b, d, u, v, w)
+  #pragma omp distribute simd firstprivate (a, b)
+  for (d = a; d < b; d++)
+    u[d] = v[d] + w[d];
+  return d;
+}
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+  long d, e;
+  #pragma omp teams default(none) firstprivate (a, b, c) shared(d, e, u, v, w)
+  #pragma omp distribute simd linear(d) lastprivate(e)
+  for (d = a; d < b; d++)
+    {
+      u[d] = v[d] + w[d];
+      e = c + d * 5;
+    }
+  return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams default(none) shared(a1, b1, a2, b2, d1, d2, u, v, w)
+  #pragma omp distribute simd firstprivate (a1, b1, a2, b2) lastprivate(d1, d2) collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+__attribute__((noinline, noclone)) long
+f4 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams default(none) firstprivate (a1, b1, a2, b2) shared(d1, d2, u, v, w)
+  #pragma omp distribute simd collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+int
+main ()
+{
+  if (f1 (0, 1024) != 1024
+      || f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+      || f3 (0, 32, 0, 32) != 64
+      || f4 (0, 32, 0, 32) != 64)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/pr66199-14.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/pr66199-14.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,39 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+  long d, e;
+  #pragma omp teams default(none) firstprivate (a, b, c) shared(d, e, u, v, w)
+  #pragma omp distribute lastprivate(d, e)
+  for (d = a; d < b; d++)
+    {
+      u[d] = v[d] + w[d];
+      e = c + d * 5;
+    }
+  return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+  long d1, d2;
+  #pragma omp teams default(none) shared(a1, b1, a2, b2, d1, d2, u, v, w)
+  #pragma omp distribute firstprivate (a1, b1, a2, b2) lastprivate(d1, d2) collapse(2)
+  for (d1 = a1; d1 < b1; d1++)
+    for (d2 = a2; d2 < b2; d2++)
+      u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+  return d1 + d2;
+}
+
+int
+main ()
+{
+  if (f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+      || f3 (0, 32, 0, 32) != 64)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/simd-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/simd-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,71 @@
+// { dg-do run }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#define N 1024
+int a[N], b[N];
+
+int
+f1 (void)
+{
+  int i;
+  #pragma omp simd private (i)
+  for (i = 0; i < N; i++)
+    a[i] = b[i] * 2;
+  #pragma omp simd lastprivate (i)
+  for (i = 0; i < N; i++)
+    a[i] += b[i] * 2;
+  return i;
+}
+
+int
+f2 (void)
+{
+  int i, j;
+  #pragma omp simd private (i), collapse (2), lastprivate (j)
+  for (i = 0; i < 32; i++)
+    for (j = 0; j < 32; ++j)
+      a[i * 32 + j] += b[i * 32 + j] * 2;
+  return j;
+}
+
+int
+f3 (void)
+{
+  static int i;
+  #pragma omp for simd private (i)
+  for (i = 0; i < N; ++i)
+    a[i] = b[i] * 2;
+  #pragma omp for simd lastprivate (i)
+  for (i = 0; i < N; ++i)
+    a[i] += b[i] * 2;
+  return i;
+}
+
+int
+f4 (void)
+{
+  static int i, j;
+  #pragma omp for simd private (i)collapse (2)lastprivate (j)
+  for (i = 0; i < 32; ++i)
+    for (j = 0; j < 32; j++)
+      a[i * 32 + j] += b[i * 32 + j] * 2;
+  return j;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < N; ++i)
+    a[i] = b[i] = i;
+  if (f1 () != 1024 || f2 () != 32)
+    __builtin_abort ();
+  #pragma omp parallel num_threads(4)
+  if (f3 () != 1024 || f4 () != 32)
+    __builtin_abort ();
+  for (i = 0; i < N; ++i)
+    if (a[i] != 6 * i || b[i] != i)
+      __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,119 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+struct S { unsigned long long int s, t; };
+
+void
+rbar (struct S *p, struct S *o)
+{
+  p->s = 1;
+  if (o->t != 5)
+    abort ();
+  p->t = 9;
+}
+
+static inline void
+rbaz (struct S *o, struct S *i)
+{
+  if (o->t != 5 || i->t != 9)
+    abort ();
+  o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) \
+  initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : rbaz (&omp_out, &omp_in)) \
+  initializer (rbar (&omp_priv, &omp_orig))
+
+struct S g = { 0, 7 };
+struct S h = { 1, 5 };
+
+int
+foo (int *a, int *b)
+{
+  int x = 0;
+  #pragma omp taskloop reduction (+:x) in_reduction (+:b[0])
+  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 x = 1;
+  #pragma omp taskloop reduction (*:x) in_reduction (*:b[0])
+  for (int i = 0; i < 64; i++)
+    {
+      #pragma omp task in_reduction (*:x)
+      x *= a[i];
+      #pragma omp task in_reduction (*:b[0])
+      *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 ();
+  }
+}
+
+int
+main ()
+{
+  int i, j, a[64], b = 0, c[64];
+  unsigned long long int d = 1, e;
+  struct S m = { 0, 7 };
+  for (i = 0; i < 64; i++)
+    {
+      a[i] = 2 * i;
+      c[i] = 1 + ((i % 3) != 1);
+    }
+  #pragma omp parallel
+  #pragma omp master
+  {
+    struct S n = { 1, 5 };
+    #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 (m.s != 63 * 64 * 4 || m.t != 7)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-2.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,212 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+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;
+  #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] += 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;
+    }
+}
+
+void
+test (int n)
+{
+  int c[2] = { 0, 0 };
+  int p[3] = { 0, 1, 4 };
+  int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+  long long ss[4] = { 5, 1, 1, 6 };
+  long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+  s = ss;
+  t = tt;
+  #pragma omp parallel
+  #pragma omp single
+  {
+    long long int d[] = { 1, 1 };
+    int m[3] = { 5, 0, 5 };
+    int r[5] = { 6, 7, 0, 0, 9 };
+    int o[4] = { 1, 0, 0, 2 };
+    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 (default, +: 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] += 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;
+	#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] += 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;
+	    foo (n, c, d, m, r, o, p, 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
+      || ss[0] != 5
+      || ss[1] != 1LL << (16 + 4)
+      || ss[2] != 1LL << 8
+      || ss[3] != 6
+      || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+      || tt[2][0] != 1LL << (16 + 8)
+      || tt[2][1] != 1LL << 4
+      || tt[3][0] != 1LL << 8
+      || tt[3][1] != 1LL << (16 + 4)
+      || tt[4][0] != 13 || tt[4][1] != 14)
+    abort ();
+}
+
+int
+main ()
+{
+  test (1);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#define N 1024
+long int u[N], m, n;
+
+__attribute__((noipa)) void
+foo (void)
+{
+  int i;
+  #pragma omp taskloop simd reduction (+:m) grainsize (64)
+  for (i = 0; i < N; ++i)
+    m += u[i];
+}
+
+__attribute__((noipa)) void
+bar (int x)
+{
+  #pragma omp taskloop simd in_reduction (+:n) grainsize (64) nogroup
+  for (int i = (x & 1) * (N / 2); i < (x & 1) * (N / 2) + (N / 2); i++)
+    n += 2 * u[i];
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < N; ++i)
+    u[i] = i;
+  #pragma omp parallel master
+  {
+    foo ();
+    #pragma omp taskgroup task_reduction (+:n)
+    {
+      bar (0);
+      bar (1);
+    }
+  }
+  if (m != (long)(N - 1) * (N / 2) || n != (long)(N - 1) * N)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+#define N 1024
+long int u[N], m, n, o;
+
+__attribute__((noipa)) void
+foo (void)
+{
+  int i = -1;
+  #pragma omp master taskloop simd reduction (+:m) grainsize (64)
+  for (i = 0; i < N; ++i)
+    m += u[i];
+  if (i != (omp_get_thread_num () ? -1 : N))
+    abort ();
+}
+
+__attribute__((noipa)) void
+bar (int x)
+{
+  int i = -1;
+  #pragma omp master taskloop simd in_reduction (+:n) grainsize (64)
+  for (i = (x & 1) * (N / 2); i < (x & 1) * (N / 2) + (N / 2); i++)
+    n += 2 * u[i];
+  if (i != (omp_get_thread_num () ? -1 : (x & 1) * (N / 2) + (N / 2)))
+    abort ();
+}
+
+__attribute__((noipa)) void
+baz (void)
+{
+  int i;
+  #pragma omp parallel master taskloop simd reduction (+:o) grainsize (64)
+  for (i = 0; i < N; ++i)
+    o += u[i];
+  if (i != N)
+    abort ();
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < N; ++i)
+    u[i] = i;
+  #pragma omp parallel
+  {
+    foo ();
+    #pragma omp taskgroup task_reduction (+:n)
+    {
+      bar (0);
+      bar (1);
+    }
+  }
+  baz ();
+  if (m != (long)(N - 1) * (N / 2) || n != (long)(N - 1) * N || o != m)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-11.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-11.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,56 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+int a, b[3] = { 1, 1, 1 };
+unsigned long int c[2] = { ~0UL, ~0UL };
+
+void
+bar (int i)
+{
+  #pragma omp task in_reduction (*: b[:3]) in_reduction (&: c[1:]) \
+	      in_reduction (+: a)
+  {
+    a += 4;
+    b[1] *= 4;
+    c[1] &= ~(1UL << (i + 16));
+  }
+}
+
+void
+foo (unsigned long long int x, unsigned long long int y, unsigned long long int z)
+{
+  unsigned long long int i;
+  #pragma omp for schedule(runtime) reduction (task, +: a) \
+		  reduction (task, *: b) reduction (task, &: c[1:1])
+  for (i = x; i < y; i += z)
+    {
+      a++;
+      b[0] *= 2;
+      bar (i);
+      b[2] *= 3;
+      c[1] &= ~(1UL << i);
+    }
+}
+
+int
+main ()
+{
+  volatile int two = 2;
+  foo (two, 7 * two, two);
+  if (a != 30 || b[0] != 64 || b[1] != (1 << 12) || b[2] != 3 * 3 * 3 * 3 * 3 * 3
+      || c[0] != ~0UL || c[1] != ~0x15541554UL)
+    abort ();
+  a = 0;
+  b[0] = 1;
+  b[1] = 1;
+  b[2] = 1;
+  c[1] = ~0UL;
+  #pragma omp parallel
+  foo (two, 8 * two, two);
+  if (a != 35 || b[0] != 128 || b[1] != (1 << 14) || b[2] != 3 * 3 * 3 * 3 * 3 * 3 * 3
+      || c[0] != ~0UL || c[1] != ~0x55545554UL)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-12.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-12.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,67 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+int a, b[3] = { 1, 1, 1 };
+unsigned long int c[2] = { ~0UL, ~0UL };
+
+void
+bar (int i)
+{
+  #pragma omp task in_reduction (*: b[:3]) in_reduction (&: c[1:]) \
+	      in_reduction (+: a)
+  {
+    a += 4;
+    b[1] *= 4;
+    c[1] &= ~(1UL << (i + 16));
+  }
+}
+
+void
+foo (int x)
+{
+  #pragma omp sections reduction (task, +: a) reduction (task, *: b) \
+		       reduction (task, &: c[1:1])
+  {
+    {
+      a++; b[0] *= 2; bar (2); b[2] *= 3; c[1] &= ~(1UL << 2);
+    }
+    #pragma omp section
+    { b[0] *= 2; bar (4); b[2] *= 3; c[1] &= ~(1UL << 4); a++; }
+    #pragma omp section
+    { bar (6); b[2] *= 3; c[1] &= ~(1UL << 6); a++; b[0] *= 2; }
+    #pragma omp section
+    { b[2] *= 3; c[1] &= ~(1UL << 8); a++; b[0] *= 2; bar (8); }
+    #pragma omp section
+    { c[1] &= ~(1UL << 10); a++; b[0] *= 2; bar (10); b[2] *= 3; }
+    #pragma omp section
+    { a++; b[0] *= 2; b[2] *= 3; c[1] &= ~(1UL << 12); bar (12); }
+    #pragma omp section
+    if (x)
+      {
+	a++; b[0] *= 2; b[2] *= 3; bar (14); c[1] &= ~(1UL << 14);
+      }
+  }
+}
+
+int
+main ()
+{
+  volatile int one = 1;
+  foo (!one);
+  if (a != 30 || b[0] != 64 || b[1] != (1 << 12) || b[2] != 3 * 3 * 3 * 3 * 3 * 3
+      || c[0] != ~0UL || c[1] != ~0x15541554UL)
+    abort ();
+  a = 0;
+  b[0] = 1;
+  b[1] = 1;
+  b[2] = 1;
+  c[1] = ~0UL;
+  #pragma omp parallel
+  foo (one);
+  if (a != 35 || b[0] != 128 || b[1] != (1 << 14) || b[2] != 3 * 3 * 3 * 3 * 3 * 3 * 3
+      || c[0] != ~0UL || c[1] != ~0x55545554UL)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,58 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a;
+long int b = 1;
+
+void
+foo (void)
+{
+  int i;
+  for (i = 0; i < 2; i++)
+    #pragma omp task in_reduction (+: a) in_reduction (*: b)
+    {
+      a += 7;
+      b *= 2;
+    }
+}
+
+int
+main ()
+{
+  int c = 0;
+  #pragma omp parallel
+  #pragma omp single
+  {
+    long int d = 1;
+    #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 += 9;
+	  d *= 3;
+	}
+    }
+#define THREEP4 (3L * 3L * 3L * 3L)
+    if (d != (THREEP4 * THREEP4 * THREEP4))
+      abort ();
+  }
+  if (a != 28 * 7 || b != (1L << 28) || c != 12 * 9)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-2.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,90 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+struct S { long int s, t; };
+
+void
+bar (struct S *p, struct S *o)
+{
+  p->s = 1;
+  if (o->t != 5)
+    abort ();
+  p->t = 9;
+}
+
+static inline void
+baz (struct S *o, struct S *i)
+{
+  if (o->t != 5 || i->t != 9)
+    abort ();
+  o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+struct S a = { 0, 7 };
+struct S b = { 1, 5 };
+
+void
+foo (void)
+{
+  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 ();
+    }
+}
+
+int
+main ()
+{
+  struct S c = { 0, 7 };
+  #pragma omp parallel
+  #pragma omp single
+  {
+    struct 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 ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-3.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-3.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,218 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+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;
+  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;
+    }
+}
+
+void
+test (int n)
+{
+  int c[2] = { 0, 0 };
+  int p[3] = { 0, 1, 4 };
+  int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+  long long ss[4] = { 5, 1, 1, 6 };
+  long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+  s = ss;
+  t = tt;
+  #pragma omp parallel
+  #pragma omp single
+  {
+    long long int d[] = { 1, 1 };
+    int m[3] = { 5, 0, 5 };
+    int r[5] = { 6, 7, 0, 0, 9 };
+    int o[4] = { 1, 0, 0, 2 };
+    #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] += 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;
+	      foo (n, c, d, m, r, o, p, 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
+      || ss[0] != 5
+      || ss[1] != 1LL << (16 + 4)
+      || ss[2] != 1LL << 8
+      || ss[3] != 6
+      || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+      || tt[2][0] != 1LL << (16 + 8)
+      || tt[2][1] != 1LL << 4
+      || tt[3][0] != 1LL << 8
+      || tt[3][1] != 1LL << (16 + 4)
+      || tt[4][0] != 13 || tt[4][1] != 14)
+    abort ();
+}
+
+int
+main ()
+{
+  test (1);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-4.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-4.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,70 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+void
+bar (long long int *p)
+{
+  p[0] *= 2;
+  #pragma omp task in_reduction (*: p[0])
+  p[0] *= 3;
+}
+
+void
+foo (long long int *p, long long int *q)
+{
+  #pragma omp taskgroup task_reduction (*: p[0])
+  {
+    #pragma omp task in_reduction (*: p[0])
+    bar (p);
+    #pragma omp task in_reduction (*: p[0])
+    bar (p);
+    bar (p);
+    #pragma omp taskgroup task_reduction (*: q[0])
+    {
+      #pragma omp task in_reduction (*: q[0])
+      bar (q);
+      #pragma omp task in_reduction (*: q[0])
+      bar (q);
+      #pragma omp task in_reduction (*: q[0])
+      bar (q);
+      bar (q);
+      #pragma omp task in_reduction (*: p[0])
+      {
+	#pragma omp taskgroup task_reduction (*: p[0])
+	{
+	  #pragma omp task in_reduction (*: p[0])
+	  bar (p);
+	  p[0] *= 2;
+	  #pragma omp task in_reduction (*: p[0])
+	  bar (p);
+	}
+      }
+    }
+  }
+}
+
+int
+main ()
+{
+  long long int p = 1LL, q = 1LL;
+  foo (&p, &q);
+  if (p != 6LL * 6LL * 6LL * 6LL * 6LL * 2LL || q != 6LL * 6LL * 6LL * 6LL)
+    abort ();
+  p = 1LL;
+  q = 1LL;
+  #pragma omp taskgroup
+  foo (&p, &q);
+  if (p != 6LL * 6LL * 6LL * 6LL * 6LL * 2LL || q != 6LL * 6LL * 6LL * 6LL)
+    abort ();
+  p = 1LL;
+  q = 1LL;
+  #pragma omp parallel
+  #pragma omp single
+  foo (&p, &q);
+  if (p != 6LL * 6LL * 6LL * 6LL * 6LL * 2LL || q != 6LL * 6LL * 6LL * 6LL)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,65 @@
+typedef __SIZE_TYPE__ size_t;
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+int *q;
+
+void
+bar (int *p, int *r, int *t, int s, size_t u)
+{
+  #pragma omp task in_reduction (*: p[0], q[0], r[s - 1], t[0:u + 1])
+  {
+    *p *= 4;
+    *q *= 5;
+    r[s - 1] *= 6;
+    t[0] *= 8;
+    t[1] *= 9;
+  }
+}
+
+void
+foo (int *p, int *r, int *t, int s, size_t u)
+{
+  int *p2 = p;
+  #pragma omp taskgroup task_reduction (*: p[0], q[0], r[s], t[0:u + 1])
+  {
+    p = (int *) 0;
+    s++;
+    bar (p2, r, t, s, u);
+    r++;
+    #pragma omp taskwait
+    #pragma omp task in_reduction (*: p2[0], q[0], r[s - 2], t[0:u + 1])
+    {
+      *p2 *= 2;
+      *q *= 3;
+      r[s - 2] *= 7;
+      t[0] *= 10;
+      t[1] *= 11;
+    }
+    u = (~(size_t) 0) / 4;
+    s++;
+    p2 = (int *) 0;
+    q = (int *) 0;
+    r = (int *) 0;
+    t = (int *) 0;
+  }
+}
+
+int
+main ()
+{
+  int a = 1, b = 1, c[2] = { 1, 0 }, d[3] = { 1, 1, -1 };
+  volatile int zero;
+  zero = 0;
+  q = &b;
+  #pragma omp parallel num_threads (2)
+  #pragma omp master
+  foo (&a, &c[0], &d[0], zero, zero + 1);
+  if (a != 8 || b != 15 || c[0] != 42 || c[1] != 0
+      || d[0] != 80 || d[1] != 99 || d[2] != -1)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-6.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-6.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,125 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct S { unsigned long long int s, t; };
+
+void
+rbar (struct S *p, struct S *o)
+{
+  p->s = 1;
+  if (o->t != 5)
+    abort ();
+  p->t = 9;
+}
+
+static inline void
+rbaz (struct S *o, struct S *i)
+{
+  if (o->t != 5 || i->t != 9)
+    abort ();
+  o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) \
+  initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : rbaz (&omp_out, &omp_in)) \
+  initializer (rbar (&omp_priv, &omp_orig))
+
+struct S g = { 0, 7 };
+struct S h = { 1, 5 };
+
+int
+foo (int *a, int *b)
+{
+  int x = 0;
+  #pragma omp taskloop reduction (+:x) in_reduction (+:b[0])
+  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 x = 1;
+  #pragma omp taskloop reduction (*:x) in_reduction (*:b[0])
+  for (int i = 0; i < 64; i++)
+    {
+      #pragma omp task in_reduction (*:x)
+      x *= a[i];
+      #pragma omp task in_reduction (*:b[0])
+      *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 ();
+  }
+}
+
+int
+main ()
+{
+  int i, j, a[64], b = 0, c[64];
+  unsigned long long int d = 1, e;
+  int r = 0, t;
+  struct S m = { 0, 7 };
+  struct S n = { 1, 5 };
+  for (i = 0; i < 64; i++)
+    {
+      a[i] = 2 * i;
+      c[i] = 1 + ((i % 3) != 1);
+    }
+  #pragma omp parallel reduction (task, +:b) reduction(+:r) \
+		       reduction(task,*:d) reduction (task, +: g, m) \
+		       reduction (task, *: h, n) shared(t)
+  {
+    #pragma omp master
+    {
+      j = foo (a, &b);
+      t = omp_get_num_threads ();
+    }
+    r++;
+    #pragma omp single nowait
+      e = bar (c, &d);
+    #pragma omp master
+    #pragma omp taskloop in_reduction (+: g, m) in_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 (m.s != 63 * 64 * 4 || m.t != 7)
+    abort ();
+  if (r != t)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-7.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-7.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,216 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+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;
+  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;
+    }
+}
+
+void
+test (int n)
+{
+  int c[2] = { 0, 0 };
+  int p[3] = { 0, 1, 4 };
+  int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+  long long ss[4] = { 5, 1, 1, 6 };
+  long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+  long long int d[] = { 1, 1 };
+  int m[3] = { 5, 0, 5 };
+  int r[5] = { 6, 7, 0, 0, 9 };
+  int o[4] = { 1, 0, 0, 2 };
+  s = ss;
+  t = tt;
+  #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]) num_threads(4)
+  {
+    int i;
+    #pragma omp for
+    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] += 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;
+	      foo (n, c, d, m, r, o, p, 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 (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
+      || d[0] != 1LL << (8 + 4)
+      || d[1] != 1LL << 16
+      || 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
+      || m[0] != 5
+      || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+      || m[2] != 5
+      || o[0] != 1
+      || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+      || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+      || o[3] != 2
+      || 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
+      || 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
+      || ss[0] != 5
+      || ss[1] != 1LL << (16 + 4)
+      || ss[2] != 1LL << 8
+      || ss[3] != 6
+      || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+      || tt[2][0] != 1LL << (16 + 8)
+      || tt[2][1] != 1LL << 4
+      || tt[3][0] != 1LL << 8
+      || tt[3][1] != 1LL << (16 + 4)
+      || tt[4][0] != 13 || tt[4][1] != 14)
+    abort ();
+}
+
+int
+main ()
+{
+  test (1);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-8.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-8.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,141 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct S { unsigned long long int s, t; };
+
+void
+rbar (struct S *p, struct S *o)
+{
+  p->s = 1;
+  if (o->t != 5)
+    abort ();
+  p->t = 9;
+}
+
+static inline void
+rbaz (struct S *o, struct S *i)
+{
+  if (o->t != 5 || i->t != 9)
+    abort ();
+  o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) \
+  initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : rbaz (&omp_out, &omp_in)) \
+  initializer (rbar (&omp_priv, &omp_orig))
+
+struct S g = { 0, 7 };
+struct S h = { 1, 5 };
+
+int
+foo (int z, int *a, int *b)
+{
+  int x = 0;
+  #pragma omp taskloop reduction (+:x) in_reduction (+:b[0])
+  for (int i = z; i < z + 8; i++)
+    {
+      x += a[i];
+      *b += a[i] * 2;
+    }
+  return x;
+}
+
+unsigned long long int
+bar (int z, int *a, unsigned long long int *b, int *s)
+{
+  unsigned long long int x = 1;
+  #pragma omp taskloop reduction (*:x) in_reduction (*:b[0])
+  for (int i = z; i < z + 8; i++)
+    {
+      #pragma omp task in_reduction (*:x)
+      x *= a[i];
+      #pragma omp task in_reduction (*:b[0])
+      *b *= (3 - a[i]);
+      s[0]++;
+    }
+  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 ();
+  }
+}
+
+int
+main ()
+{
+  int i, j = 0, a[64], b = 0, c[64], f = 0;
+  unsigned long long int d = 1, e = 1;
+  volatile int one = 1;
+  int r = 0, s = 0, t;
+  struct S m = { 0, 7 };
+  struct S n = { 1, 5 };
+  for (i = 0; i < 64; i++)
+    {
+      a[i] = 2 * i;
+      c[i] = 1 + ((i % 3) != 1);
+    }
+  #pragma omp parallel reduction (task, +:b) shared(t) reduction(+:r, s)
+  {
+    int z, q1, q2, q3;
+    #pragma omp master
+    t = omp_get_num_threads ();
+    #pragma omp for schedule(static) reduction (task, +: f) reduction (+: j)
+    for (z = 0; z < 64; z += 8)
+      {
+	f++;
+	j += foo (z, a, &b);
+	j += foo (z, a, &f);
+      }
+    if (j != 63 * 64 * 2 || f != 63 * 64 * 2 + 8)
+      abort ();
+    r++;
+    #pragma omp taskgroup task_reduction (+: s)
+    {
+      #pragma omp for schedule(static, 1) reduction(task, *: d) reduction (*: e)
+      for (z = 0; z < 64; z += 8)
+	e *= bar (z, c, &d, &s);
+    }
+    if (e != (1ULL << 43) || d != (1ULL << 21))
+      abort ();
+    #pragma omp for schedule(monotonic: dynamic, 1) reduction (task, +: g, m) \
+		    reduction (task, *: h, n) collapse(3)
+    for (q1 = 0; q1 < one; q1++)
+      for (q2 = 0; q2 < 64; q2 += 8)
+	for (q3 = 0; q3 < one; ++q3)
+	  #pragma omp taskloop in_reduction (+: g, m) in_reduction (*: h, n) \
+			       nogroup
+	  for (i = q2; i < q2 + 8; ++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 (g.s != 63 * 64 * 10 || g.t != 7)
+      abort ();
+    if (h.s != (1ULL << 42) || h.t != 5)
+      abort ();
+    if (m.s != 63 * 64 * 4 || m.t != 7)
+      abort ();
+  }
+  if (b != 63 * 64 * 2)
+    abort ();
+  if (r != t || s != 64)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/task-reduction-9.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-9.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,217 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+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;
+  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;
+    }
+}
+
+void
+test (int n)
+{
+  int c[2] = { 0, 0 };
+  int p[3] = { 0, 1, 4 };
+  int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+  long long ss[4] = { 5, 1, 1, 6 };
+  long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+  long long int d[] = { 1, 1 };
+  int m[3] = { 5, 0, 5 };
+  int r[5] = { 6, 7, 0, 0, 9 };
+  int o[4] = { 1, 0, 0, 2 };
+  s = ss;
+  t = tt;
+  #pragma omp parallel num_threads(4)
+  {
+    int i;
+    #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: runtime)
+    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] += 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;
+	      foo (n, c, d, m, r, o, p, 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 (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
+      || d[0] != 1LL << (8 + 4)
+      || d[1] != 1LL << 16
+      || 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
+      || m[0] != 5
+      || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+      || m[2] != 5
+      || o[0] != 1
+      || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+      || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+      || o[3] != 2
+      || 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
+      || 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
+      || ss[0] != 5
+      || ss[1] != 1LL << (16 + 4)
+      || ss[2] != 1LL << 8
+      || ss[3] != 6
+      || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+      || tt[2][0] != 1LL << (16 + 8)
+      || tt[2][1] != 1LL << 4
+      || tt[3][0] != 1LL << 8
+      || tt[3][1] != 1LL << (16 + 4)
+      || tt[4][0] != 13 || tt[4][1] != 14)
+    abort ();
+}
+
+int
+main ()
+{
+  test (1);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,29 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int
+main ()
+{
+  int a, b, c, d;
+  #pragma omp parallel num_threads (4)
+  #pragma omp single
+  {
+    #pragma omp task depend(out : a)
+    a = 6;
+    #pragma omp task depend(out : b)
+    b = 7;
+    #pragma omp task depend(out : c)
+    c = 8;
+    #pragma omp taskwait depend(in : a, c)
+    d = a + c;
+    #pragma omp task depend(out : a)
+    a = 9;
+    #pragma omp task depend(out : c)
+    c = 10;
+  }
+  if (a != 9 || b != 7 || c != 10 || d != 6 + 8)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/depend-1.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/depend-1.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/depend-iterator-1.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/depend-iterator-1.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/depobj-1.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/depobj-1.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/for-16.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-16.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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);
+}
--- libgomp/testsuite/libgomp.c++/for-21.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-21.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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);
+}
--- libgomp/testsuite/libgomp.c++/for-22.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-22.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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);
+}
--- libgomp/testsuite/libgomp.c++/for-23.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-23.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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);
+}
--- libgomp/testsuite/libgomp.c++/for-24.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-24.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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);
+}
--- libgomp/testsuite/libgomp.c++/for-25.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-25.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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);
+  }
+}
--- libgomp/testsuite/libgomp.c++/for-26.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-26.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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);
+}
--- libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-10.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-10.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-11.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-11.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-12.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-12.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-13.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-13.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-14.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-14.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-15.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-15.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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> ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-16.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-16.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-17.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-17.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-18.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-18.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-19.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-19.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c/task-reduction-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c/task-reduction-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,137 @@
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+
+void
+bar (int *a, int *b, int *c, int (*d)[2], int (*e)[4], size_t n, int f[1][n], int g[1][n * 2])
+{
+  #pragma omp task in_reduction (*: a[:n], b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][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][0] *= 22;
+    f[0][1] *= 23;
+    g[0][1] *= 24;
+    g[0][2] *= 25;
+  }
+}
+
+void
+foo (size_t n, void *x, void *y, int f[1][n], int g[1][n * 2])
+{
+  int a[n], b[n + 3], c[2 * n];
+  int (*d)[n] = (int (*)[n]) x;
+  int (*e)[n * 2] = (int (*)[n * 2]) y;
+  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[0][i] = 1;
+      g[0][i + 1] = 1;
+    }
+  #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+  {
+    bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, n, f, g);
+    #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][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][0] *= 12;
+      f[0][1] *= 13;
+      g[0][1] *= 14;
+      g[0][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][0] != 264 || f[0][1] != 299)
+    abort ();
+  if (g[0][1] != 336 || g[0][2] != 375)
+    abort ();
+}
+
+void
+baz (size_t n, void *x, void *y, int f[1][n], int g[1][n * 2])
+{
+  int a[n], b[n + 3], c[2 * n];
+  int (*d)[n] = (int (*)[n]) x;
+  int (*e)[n * 2] = (int (*)[n * 2]) y;
+  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[0][i] = 1;
+      g[0][i + 1] = 1;
+    }
+  #pragma omp parallel num_threads(2)
+  #pragma omp master
+  #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+  {
+    bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, n, f, g);
+    #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][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][0] *= 12;
+      f[0][1] *= 13;
+      g[0][1] *= 14;
+      g[0][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][0] != 264 || f[0][1] != 299)
+    abort ();
+  if (g[0][1] != 336 || g[0][2] != 375)
+    abort ();
+}
+
+int
+main ()
+{
+  int d[1][2], e[1][4], f[1][2], g[1][4];
+  volatile int two;
+  two = 2;
+  #pragma omp parallel num_threads (2)
+  #pragma omp master
+  foo (two, (void *) d, (void *) e, f, g);
+  baz (two, (void *) d, (void *) e, f, g);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-1.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-1.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c/task-reduction-2.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c/task-reduction-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,86 @@
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+
+void
+bar (int *a, int *b, int *c, int (*d)[2], int (*e)[4], size_t n, int f[1][n], int g[1][n * 2])
+{
+  #pragma omp task in_reduction (*: a[:n], b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][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][0] *= 22;
+    f[0][1] *= 23;
+    g[0][1] *= 24;
+    g[0][2] *= 25;
+  }
+}
+
+void
+baz (size_t n, void *x, void *y, int f[1][n], int g[1][n * 2])
+{
+  int a[n], b[n + 3], c[2 * n];
+  int (*d)[n] = (int (*)[n]) x;
+  int (*e)[n * 2] = (int (*)[n * 2]) y;
+  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[0][i] = 1;
+      g[0][i + 1] = 1;
+    }
+  #pragma omp parallel num_threads(2) firstprivate (n) \
+		       reduction (task, *: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+  {
+    #pragma omp master
+    bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, n, f, g);
+    #pragma omp master
+    #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][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][0] *= 12;
+      f[0][1] *= 13;
+      g[0][1] *= 14;
+      g[0][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][0] != 264 || f[0][1] != 299)
+    abort ();
+  if (g[0][1] != 336 || g[0][2] != 375)
+    abort ();
+}
+
+int
+main ()
+{
+  int d[1][2], e[1][4], f[1][2], g[1][4];
+  volatile int two;
+  two = 2;
+  baz (two, (void *) d, (void *) e, f, g);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-2.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-2.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-3.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-3.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-4.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-4.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-5.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-5.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-6.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-6.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-7.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-7.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-8.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-8.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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> ();
+}
--- libgomp/testsuite/libgomp.c++/task-reduction-9.C	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/task-reduction-9.C	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -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 ();
+}
--- libgomp/testsuite/libgomp.c/teams-1.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c/teams-1.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,27 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+  #pragma omp teams thread_limit (2)
+  {
+    if (omp_in_parallel ()
+	|| omp_get_level () != 0
+	|| omp_get_ancestor_thread_num (0) != 0
+	|| omp_get_ancestor_thread_num (1) != -1)
+      abort ();
+    omp_set_dynamic (0);
+    omp_set_nested (1);
+    #pragma omp parallel num_threads (2)
+    {
+      if (!omp_in_parallel ()
+	  || omp_get_level () != 1
+	  || omp_get_ancestor_thread_num (0) != 0
+	  || omp_get_ancestor_thread_num (1) != omp_get_thread_num ()
+	  || omp_get_ancestor_thread_num (2) != -1)
+	abort ();
+    }
+  }
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/teams-2.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c/teams-2.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,123 @@
+#include <omp.h>
+#include <stdlib.h>
+
+__attribute__((noinline))
+void
+foo (int x, int y, int z, int *a, int *b)
+{
+  if (x == 0)
+    {
+      int i, j;
+      for (i = 0; i < 64; i++)
+	#pragma omp parallel for shared (a, b)
+	for (j = 0; j < 32; j++)
+	  foo (3, i, j, a, b);
+    }
+  else if (x == 1)
+    {
+      int i, j;
+      #pragma omp distribute dist_schedule (static, 1)
+      for (i = 0; i < 64; i++)
+	#pragma omp parallel for shared (a, b)
+	for (j = 0; j < 32; j++)
+	  foo (3, i, j, a, b);
+    }
+  else if (x == 2)
+    {
+      int j;
+      #pragma omp parallel for shared (a, b)
+      for (j = 0; j < 32; j++)
+	foo (3, y, j, a, b);
+    }
+  else
+    {
+      #pragma omp atomic
+      b[y] += z;
+      #pragma omp atomic
+      *a += 1;
+    }
+}
+
+__attribute__((noinline))
+int
+bar (int x, int y, int z)
+{
+  int a, b[64], i;
+  a = 8;
+  for (i = 0; i < 64; i++)
+    b[i] = i;
+  foo (x, y, z, &a, b);
+  if (x == 0)
+    {
+      if (a != 8 + 64 * 32)
+	return 1;
+      for (i = 0; i < 64; i++)
+	if (b[i] != i + 31 * 32 / 2)
+	  return 1;
+    }
+  else if (x == 1)
+    {
+      int c = omp_get_num_teams ();
+      int d = omp_get_team_num ();
+      int e = d;
+      int f = 0;
+      for (i = 0; i < 64; i++)
+	if (i == e)
+	  {
+	    if (b[i] != i + 31 * 32 / 2)
+	      return 1;
+	    f++;
+	    e = e + c;
+	  }
+	else if (b[i] != i)
+	  return 1;
+      if (a < 8 || a > 8 + f * 32)
+	return 1;
+    }
+  else if (x == 2)
+    {
+      if (a != 8 + 32)
+	return 1;
+      for (i = 0; i < 64; i++)
+	if (b[i] != i + (i == y ? 31 * 32 / 2 : 0))
+	  return 1;
+    }
+  else if (x == 3)
+    {
+      if (a != 8 + 1)
+	return 1;
+      for (i = 0; i < 64; i++)
+	if (b[i] != i + (i == y ? z : 0))
+	  return 1;
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  int i, j, err = 0;
+  #pragma omp teams reduction(+:err)
+  err += bar (0, 0, 0);
+  if (err)
+    abort ();
+  #pragma omp teams reduction(+:err)
+  err += bar (1, 0, 0);
+  if (err)
+    abort ();
+  #pragma omp teams reduction(+:err)
+  #pragma omp distribute
+  for (i = 0; i < 64; i++)
+    err += bar (2, i, 0);
+  if (err)
+    abort ();
+  #pragma omp teams reduction(+:err)
+  #pragma omp distribute
+  for (i = 0; i < 64; i++)
+  #pragma omp parallel for reduction(+:err)
+    for (j = 0; j < 32; j++)
+      err += bar (3, i, j);
+  if (err)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/thread-limit-4.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c/thread-limit-4.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_THREAD_LIMIT "9" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <omp.h>
+
+int
+main ()
+{
+  if (omp_get_thread_limit () != 9)
+    return 0;
+  omp_set_dynamic (0);
+  #pragma omp parallel num_threads (8)
+  if (omp_get_num_threads () != 8)
+    abort ();
+  #pragma omp parallel num_threads (16)
+  if (omp_get_num_threads () > 9)
+    abort ();
+  #pragma omp teams thread_limit (6)
+  {
+    if (omp_get_thread_limit () > 6)
+      abort ();
+    if (omp_get_thread_limit () == 6)
+      {
+	omp_set_dynamic (0);
+	omp_set_nested (1);
+	#pragma omp parallel num_threads (3)
+	if (omp_get_num_threads () != 3)
+	  abort ();
+	#pragma omp parallel num_threads (3)
+	if (omp_get_num_threads () != 3)
+	  abort ();
+	#pragma omp parallel num_threads (8)
+	if (omp_get_num_threads () > 6)
+	  abort ();
+	#pragma omp parallel num_threads (6)
+	if (omp_get_num_threads () != 6)
+	  abort ();
+	int cnt = 0;
+	#pragma omp parallel num_threads (5)
+	#pragma omp parallel num_threads (5)
+	#pragma omp parallel num_threads (2)
+	{
+	  int v;
+	  #pragma omp atomic capture
+	  v = ++cnt;
+	  if (v > 6)
+	    abort ();
+	  usleep (10000);
+	  #pragma omp atomic
+	  --cnt;
+	}
+      }
+  }
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/thread-limit-5.c	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.c/thread-limit-5.c	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+  #pragma omp teams thread_limit (1)
+  if (omp_get_thread_limit () != 1)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.fortran/display-affinity-1.f90	(.../trunk)	(nonexistent)
+++ libgomp/testsuite/libgomp.fortran/display-affinity-1.f90	(.../branches/gomp-5_0-branch)	(revision 265887)
@@ -0,0 +1,34 @@
+! { dg-set-target-env-var OMP_PROC_BIND "spread,close" }
+! { dg-set-target-env-var OMP_PLACES "cores" }
+! { dg-set-target-env-var OMP_NUM_THREADS "4" }
+! { dg-set-target-env-var OMP_AFFINITY_FORMAT "hello" }
+
+  use omp_lib
+  character(len=68) :: buf, buf2
+  character(len=8) :: buf3
+  character(len=1) :: buf4
+  integer :: l1, l2
+
+  buf = 'L:%0.5L%%%n>%32H<!%.33{host}!%.6P_%i_%0.18i_%0.7{ancestor_tnum} %18A'
+  call omp_set_affinity_format (format = buf)
+  if (omp_get_affinity_format (buf4) /= 68) stop 1
+  if (buf4 /= 'L') stop 2
+  if (omp_get_affinity_format (buf2) /= 68) stop 3
+  if (buf2 /= buf) stop 4
+  if (omp_get_affinity_format (buf3) /= 68) stop 5
+  if (buf3 /= 'L:%0.5L%') stop 6
+  call omp_display_affinity ('')
+  call omp_display_affinity ('%%%0.9N')
+  l1 = omp_capture_affinity (buf4, '%0.5{nesting_level}%%|||%0.7a%3N!%N!')
+  buf = '%.5L%%|||%0.7{ancestor_tnum}%3{num_threads}!%{num_threads}!'
+  call omp_set_affinity_format (trim (buf))
+  l2 = omp_capture_affinity (buf2, '')
+  if (l1 /= l2) stop 7
+  if (l1 /= 22) stop 8
+  if (buf2 /= '    0%|||-0000011  !1!') stop 9
+  if (buf4 /= '0') stop 10
+!$omp parallel num_threads (4) proc_bind(spread)
+  call omp_display_affinity ('%0.2a!%n!%.4L!%N;%.2t;%0.2T;&
+                             &%{team_num};%{num_teams};%A')
+!$omp end parallel
+end
