Hi!

I've committed following patch to add support for C++ random access
iterators in taskloop constructs.

2015-06-23  Jakub Jelinek  <ja...@redhat.com>

        * tree.h (OMP_CLAUSE_PRIVATE_TASKLOOP_IV,
        OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV): Define.
        * gimplify.c (gimplify_omp_for): Handle gimplification of
        OMP_TASKLOOP with C++ random access iterator clauses.
        * omp-low.c (scan_sharing_clauses): Ignore
        OMP_CLAUSE_SHARED with OMP_CLAUSE_SHARED_FIRSTPRIVATE if
        it is a global var outside of the outer taskloop for.
        (lower_lastprivate_clauses): Handle
        OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV lastprivate if the
        decl is global outside of outer taskloop for.
        (lower_send_clauses): Look beyond the outer taskloop for.
gcc/cp/
        * semantics.c (handle_omp_for_class_iterator): Handle
        OMP_TASKLOOP class iterators.
        (finish_omp_for): Adjust handle_omp_for_class_iterator
        caller.
libgomp/
        * testsuite/libgomp.c++/taskloop-6.C: New test.
        * testsuite/libgomp.c++/taskloop-7.C: New test.
        * testsuite/libgomp.c++/taskloop-8.C: New test.
        * testsuite/libgomp.c++/taskloop-9.C: New test.

--- gcc/tree.h.jj       2015-06-17 21:02:00.000000000 +0200
+++ gcc/tree.h  2015-06-22 15:19:37.501110534 +0200
@@ -1356,6 +1356,12 @@ extern void protected_set_expr_location
 #define OMP_CLAUSE_PRIVATE_OUTER_REF(NODE) \
   TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIVATE))
 
+/* True if a PRIVATE clause is for a C++ class IV on taskloop construct
+   (thus should be private on the outer taskloop and firstprivate on
+   task).  */
+#define OMP_CLAUSE_PRIVATE_TASKLOOP_IV(NODE) \
+  TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIVATE))
+
 /* True on a LASTPRIVATE clause if a FIRSTPRIVATE clause for the same
    decl is present in the chain.  */
 #define OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE(NODE) \
@@ -1367,6 +1373,12 @@ extern void protected_set_expr_location
 #define OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ(NODE) \
   (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
 
+/* True if a LASTPRIVATE clause is for a C++ class IV on taskloop construct
+   (thus should be lastprivate on the outer taskloop and firstprivate on
+   task).  */
+#define OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV(NODE) \
+  TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LASTPRIVATE))
+
 /* True on a SHARED clause if a FIRSTPRIVATE clause for the same
    decl is present in the chain (this can happen only for taskloop
    with FIRSTPRIVATE/LASTPRIVATE on it originally.  */
--- gcc/gimplify.c.jj   2015-06-18 15:16:18.000000000 +0200
+++ gcc/gimplify.c      2015-06-23 10:03:28.908079507 +0200
@@ -7230,7 +7230,8 @@ gimplify_omp_for (tree *expr_p, gimple_s
            {
              TREE_OPERAND (t, 1)
                = get_initialized_tmp_var (TREE_OPERAND (t, 1),
-                                          pre_p, NULL);
+                                          gimple_seq_empty_p (for_pre_body)
+                                          ? pre_p : &for_pre_body, NULL);
              tree c = build_omp_clause (input_location,
                                         OMP_CLAUSE_FIRSTPRIVATE);
              OMP_CLAUSE_DECL (c) = TREE_OPERAND (t, 1);
@@ -7250,7 +7251,9 @@ gimplify_omp_for (tree *expr_p, gimple_s
 
              if (!is_gimple_constant (*tp))
                {
-                 *tp = get_initialized_tmp_var (*tp, pre_p, NULL);
+                 gimple_seq *seq = gimple_seq_empty_p (for_pre_body)
+                                   ? pre_p : &for_pre_body;
+                 *tp = get_initialized_tmp_var (*tp, seq, NULL);
                  tree c = build_omp_clause (input_location,
                                             OMP_CLAUSE_FIRSTPRIVATE);
                  OMP_CLAUSE_DECL (c) = *tp;
@@ -7683,7 +7686,6 @@ gimplify_omp_for (tree *expr_p, gimple_s
          {
          /* These clauses are allowed on task, move them there.  */
          case OMP_CLAUSE_SHARED:
-         case OMP_CLAUSE_PRIVATE:
          case OMP_CLAUSE_FIRSTPRIVATE:
          case OMP_CLAUSE_DEFAULT:
          case OMP_CLAUSE_IF:
@@ -7694,6 +7696,26 @@ gimplify_omp_for (tree *expr_p, gimple_s
            *gtask_clauses_ptr = c;
            gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
            break;
+         case OMP_CLAUSE_PRIVATE:
+           if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
+             {
+               /* We want private on outer for and firstprivate
+                  on task.  */
+               *gtask_clauses_ptr
+                 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+                                     OMP_CLAUSE_FIRSTPRIVATE);
+               OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
+               lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL);
+               gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+               *gforo_clauses_ptr = c;
+               gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+             }
+           else
+             {
+               *gtask_clauses_ptr = c;
+               gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+             }
+           break;
          /* These clauses go into outer taskloop clauses.  */
          case OMP_CLAUSE_GRAINSIZE:
          case OMP_CLAUSE_NUM_TASKS:
@@ -7712,6 +7734,26 @@ gimplify_omp_for (tree *expr_p, gimple_s
             a shared clause on task.  If the same decl is also firstprivate,
             add also firstprivate clause on the inner taskloop.  */
          case OMP_CLAUSE_LASTPRIVATE:
+           if (OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
+             {
+               /* For taskloop C++ lastprivate IVs, we want:
+                  1) private on outer taskloop
+                  2) firstprivate and shared on task
+                  3) lastprivate on inner taskloop  */
+               *gtask_clauses_ptr
+                 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+                                     OMP_CLAUSE_FIRSTPRIVATE);
+               OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
+               lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL);
+               gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+               OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
+               *gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+                                                      OMP_CLAUSE_PRIVATE);
+               OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
+               OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
+               TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
+               gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
+             }
            *gfor_clauses_ptr = c;
            gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
            *gtask_clauses_ptr
@@ -7735,7 +7777,9 @@ gimplify_omp_for (tree *expr_p, gimple_s
       g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
       gomp_for *gforo
        = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
-                               gimple_omp_for_collapse (gfor), NULL);
+                               gimple_omp_for_collapse (gfor),
+                               gimple_omp_for_pre_body (gfor));
+      gimple_omp_for_set_pre_body (gfor, NULL);
       gimple_omp_for_set_combined_p (gforo, true);
       gimple_omp_for_set_combined_into_p (gfor, true);
       for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
--- gcc/omp-low.c.jj    2015-06-22 11:17:39.000000000 +0200
+++ gcc/omp-low.c       2015-06-23 14:19:13.466669690 +0200
@@ -2169,6 +2169,9 @@ scan_sharing_clauses (tree clauses, omp_
            break;
          if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
            {
+             if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
+                                                                ctx->outer)))
+               break;
              bool by_ref = use_pointer_for_field (decl, ctx);
              install_var_field (decl, by_ref, 11, ctx);
              break;
@@ -4965,7 +4968,18 @@ lower_lastprivate_clauses (tree clauses,
              OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
            }
 
-         x = build_outer_var_ref (var, ctx, true);
+         x = NULL_TREE;
+         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+             && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
+           {
+             gcc_checking_assert (is_taskloop_ctx (ctx));
+             tree ovar = maybe_lookup_decl_in_outer_ctx (var,
+                                                         ctx->outer->outer);
+             if (is_global_var (ovar))
+               x = ovar;
+           }
+         if (!x)
+           x = build_outer_var_ref (var, ctx, true);
          if (is_reference (var))
            new_var = build_simple_mem_ref_loc (clause_loc, new_var);
          x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
@@ -5326,11 +5340,15 @@ lower_send_clauses (tree clauses, gimple
 {
   tree c, t;
   int ignored_looptemp = 0;
+  bool is_taskloop = false;
 
   /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
      by GOMP_taskloop.  */
   if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
-    ignored_looptemp = 2;
+    {
+      ignored_looptemp = 2;
+      is_taskloop = true;
+    }
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     {
@@ -5375,7 +5393,16 @@ lower_send_clauses (tree clauses, gimple
          if (is_variable_sized (val))
            continue;
        }
-      var = lookup_decl_in_outer_ctx (val, ctx);
+
+      /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
+        outer taskloop region.  */
+      omp_context *ctx_for_o = ctx;
+      if (is_taskloop
+         && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+         && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
+       ctx_for_o = ctx->outer;
+
+      var = lookup_decl_in_outer_ctx (val, ctx_for_o);
 
       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
          && is_global_var (var))
@@ -5385,7 +5412,7 @@ lower_send_clauses (tree clauses, gimple
       if (t)
        {
          var = DECL_VALUE_EXPR (var);
-         tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
+         tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
          if (o != t)
            var = unshare_and_remap (var, t, o);
          else
--- gcc/cp/semantics.c.jj       2015-06-22 11:17:39.000000000 +0200
+++ gcc/cp/semantics.c  2015-06-23 10:12:08.618129457 +0200
@@ -6791,9 +6791,10 @@ finish_omp_task (tree clauses, tree body
    into integral iterator.  Return FALSE if successful.  */
 
 static bool
-handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
-                              tree condv, tree incrv, tree *body,
-                              tree *pre_body, tree clauses, tree *lastp)
+handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
+                              tree declv, tree initv, tree condv, tree incrv,
+                              tree *body, tree *pre_body, tree &clauses,
+                              tree *lastp)
 {
   tree diff, iter_init, iter_incr = NULL, last;
   tree incr_var = NULL, orig_pre_body, orig_body, c;
@@ -6951,10 +6952,25 @@ handle_omp_for_class_iterator (int i, lo
     }
 
   incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error);
+  bool taskloop_iv_seen = false;
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
        && OMP_CLAUSE_DECL (c) == iter)
-      break;
+      {
+       if (code == OMP_TASKLOOP)
+         {
+           taskloop_iv_seen = true;
+           OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c) = 1;
+         }
+       break;
+      }
+    else if (code == OMP_TASKLOOP
+            && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+            && OMP_CLAUSE_DECL (c) == iter)
+      {
+       taskloop_iv_seen = true;
+       OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c) = 1;
+      }
 
   decl = create_temporary_var (TREE_TYPE (diff));
   pushdecl (decl);
@@ -6962,13 +6978,32 @@ handle_omp_for_class_iterator (int i, lo
   last = create_temporary_var (TREE_TYPE (diff));
   pushdecl (last);
   add_decl_expr (last);
-  if (c && iter_incr == NULL)
+  if (c && iter_incr == NULL && TREE_CODE (incr) != INTEGER_CST)
     {
       incr_var = create_temporary_var (TREE_TYPE (diff));
       pushdecl (incr_var);
       add_decl_expr (incr_var);
     }
   gcc_assert (stmts_are_full_exprs_p ());
+  tree diffvar = NULL_TREE;
+  if (code == OMP_TASKLOOP)
+    {
+      if (!taskloop_iv_seen)
+       {
+         tree ivc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
+         OMP_CLAUSE_DECL (ivc) = iter;
+         cxx_omp_finish_clause (ivc, NULL);
+         OMP_CLAUSE_CHAIN (ivc) = clauses;
+         clauses = ivc;
+       }
+      tree lvc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
+      OMP_CLAUSE_DECL (lvc) = last;
+      OMP_CLAUSE_CHAIN (lvc) = clauses;
+      clauses = lvc;
+      diffvar = create_temporary_var (TREE_TYPE (diff));
+      pushdecl (diffvar);
+      add_decl_expr (diffvar);
+    }
 
   orig_pre_body = *pre_body;
   *pre_body = push_stmt_list ();
@@ -6981,10 +7016,13 @@ handle_omp_for_class_iterator (int i, lo
   init = build_int_cst (TREE_TYPE (diff), 0);
   if (c && iter_incr == NULL)
     {
-      finish_expr_stmt (build_x_modify_expr (elocus,
-                                            incr_var, NOP_EXPR,
-                                            incr, tf_warning_or_error));
-      incr = incr_var;
+      if (incr_var)
+       {
+         finish_expr_stmt (build_x_modify_expr (elocus,
+                                                incr_var, NOP_EXPR,
+                                                incr, tf_warning_or_error));
+         incr = incr_var;
+       }
       iter_incr = build_x_modify_expr (elocus,
                                       iter, PLUS_EXPR, incr,
                                       tf_warning_or_error);
@@ -6992,6 +7030,13 @@ handle_omp_for_class_iterator (int i, lo
   finish_expr_stmt (build_x_modify_expr (elocus,
                                         last, NOP_EXPR, init,
                                         tf_warning_or_error));
+  if (diffvar)
+    {
+      finish_expr_stmt (build_x_modify_expr (elocus,
+                                            diffvar, NOP_EXPR,
+                                            diff, tf_warning_or_error));
+      diff = diffvar;
+    }
   *pre_body = pop_stmt_list (*pre_body);
 
   cond = cp_build_binary_op (elocus,
@@ -7176,8 +7221,8 @@ finish_omp_for (location_t locus, enum t
            }
          if (code == CILK_FOR && i == 0)
            orig_decl = decl;
-         if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
-                                            incrv, &body, &pre_body,
+         if (handle_omp_for_class_iterator (i, locus, code, declv, initv,
+                                            condv, incrv, &body, &pre_body,
                                             clauses, &last))
            return NULL;
          continue;
--- libgomp/testsuite/libgomp.c++/taskloop-6.C.jj       2015-06-23 
14:25:31.717932978 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-6.C  2015-06-23 15:56:31.022700214 
+0200
@@ -0,0 +1,442 @@
+// { 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
+#pragma omp single
+#pragma omp taskloop num_tasks(22)
+  for (I<int> i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop grainsize(384) private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop default(none) firstprivate (x, y)
+  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
+#pragma omp single
+#pragma omp taskloop 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
+#pragma omp single
+#pragma omp taskloop
+  for (I<int> i = x + 2000 - 64; i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (I<int> i = x + 2000 - 64; i > y + 10; i = i - 12 + 2)
+    {
+      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
+#pragma omp single
+#pragma omp taskloop default(none) firstprivate (x, y)
+  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
+#pragma omp single
+#pragma omp taskloop default(none) num_tasks(*I<int> (j.begin ())) 
firstprivate (j)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const I<T> &x, const I<T> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop grainsize(163)
+  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
+#pragma omp single
+#pragma omp taskloop
+  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 single nowait
+#pragma omp taskloop nogroup
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  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
+#pragma omp single
+#pragma omp taskloop
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+I<int>
+f14 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+I<int>
+f15 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+  return i;
+}
+
+template <int N>
+I<int>
+f16 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+  return i;
+}
+
+template <int N>
+I<int>
+f17 (J<int> j)
+{
+  static I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+  return i;
+}
+
+template <typename T, int N>
+I<T>
+f18 (const I<T> &x, const I<T> &y)
+{
+  static I<T> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i > y; i = i + N)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+T
+f19 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+  {
+#pragma omp single nowait
+#pragma omp taskloop nogroup lastprivate(i)
+    for (i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+  return i;
+}
+
+template <typename T>
+T
+f20 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop 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;
+    }
+  f1 (&a[10], &a[1990]);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (&a[0], &a[1999]);
+  check (i < 1998 && (i & 1) == 0);
+  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 >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (&a[10], &a[110]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (I<int> (), &a[12], &a[1800]);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (&a[14], &a[1803]));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (&a[33], &a[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (&a[1939], &a[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<int> > (&a[16], &a[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<int> > (&a[1761], &a[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<int> > (&a[1], &a[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f14 (&a[0], &a[1999]) != I<int>(&a[1998]))
+    abort ();
+  check (i < 1998 && (i & 1) == 0);
+  if (f15<int> (&a[0], &a[30]) != I<int>(&a[40]))
+    abort ();
+  check (i > 40 && i <= 2000 - 64);
+  if (f16<6> (I<int> (), &a[12], &a[1800]) != I<int>(&a[1814]))
+    abort ();
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  if (f17<121> (J<int> (&a[14], &a[1803])) != I<int>(&a[1926]))
+    abort ();
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  if (f18<int, -7> (&a[1939], &a[17]) != I<int>(&a[14]))
+    abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<I<int> > (&a[16], &a[1981]) != I<int>(&a[1984]))
+    abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<I<int> > (&a[1761], &a[37]) != I<int>(&a[37]))
+    abort ();
+  check (i > 37 && i <= 1761);
+  f9<long, 7> (&b[33], &b[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (&b[1939], &b[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<long> > (&b[16], &b[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<long> > (&b[1761], &b[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<long> > (&b[1], &b[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f18<long, -7> (&b[1939], &b[17]) != I<long>(&b[14]))
+    abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<I<long> > (&b[16], &b[1981]) != I<long>(&b[1984]))
+    abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<I<long> > (&b[1761], &b[37]) != I<long>(&b[37]))
+    abort ();
+  check (i > 37 && i <= 1761);
+}
--- libgomp/testsuite/libgomp.c++/taskloop-7.C.jj       2015-06-23 
14:36:24.771027568 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-7.C  2015-06-23 15:34:09.847959682 
+0200
@@ -0,0 +1,400 @@
+// { dg-do run }
+
+#include <vector>
+#include <cstdlib>
+
+template <typename T>
+class J
+{
+public:
+  typedef typename std::vector<T>::const_iterator const_iterator;
+  J(const const_iterator &x, const const_iterator &y) : b (x), e (y) {}
+  const const_iterator &begin ();
+  const const_iterator &end ();
+private:
+  const_iterator b, e;
+};
+
+template <typename T>
+const typename std::vector<T>::const_iterator &J<T>::begin () { return b; }
+template <typename T>
+const typename std::vector<T>::const_iterator &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (T &i)
+{
+  if (*i < 0 || *i >= 2000)
+    std::abort ();
+  results[*i]++;
+}
+
+void
+f1 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x + 2000 - 64; i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x + 2000 - 64;
+       i > y + 10; i = i - 12 + 2)
+    {
+      std::vector<int>::const_iterator j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (std::vector<int>::const_iterator i,
+    const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const typename std::vector<T>::const_iterator &x,
+    const typename std::vector<T>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (typename std::vector<T>::const_iterator i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const typename std::vector<T>::const_iterator &x,
+     const typename std::vector<T>::const_iterator &y)
+{
+  typename std::vector<T>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  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 single nowait
+#pragma omp taskloop nogroup
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  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
+#pragma omp single
+#pragma omp taskloop
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+std::vector<int>::const_iterator
+f14 (const std::vector<int>::const_iterator &x,
+     const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+std::vector<int>::const_iterator
+f15 (const std::vector<int>::const_iterator &x,
+     const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+  return i;
+}
+
+template <int N>
+std::vector<int>::const_iterator
+f16 (std::vector<int>::const_iterator i,
+     const std::vector<int>::const_iterator &x,
+     const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+  return i;
+}
+
+template <int N>
+std::vector<int>::const_iterator
+f17 (J<int> j)
+{
+  static std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+  return i;
+}
+
+template <typename T, int N>
+typename std::vector<T>::const_iterator
+f18 (const typename std::vector<T>::const_iterator &x,
+     const typename std::vector<T>::const_iterator &y)
+{
+  static typename std::vector<T>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i > y; i = i + N)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+T
+f19 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+  {
+#pragma omp single nowait
+#pragma omp taskloop nogroup lastprivate(i)
+    for (i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+  return i;
+}
+
+template <typename T>
+T
+f20 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop 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)                            \
+         std::abort ();                                \
+       results[i] = 0;                                 \
+      }                                                        \
+    else if (results[i])                               \
+      std::abort ()
+
+int
+main ()
+{
+  std::vector<int> a(2000);
+  std::vector<long> b(2000);
+  for (int i = 0; i < 2000; i++)
+    {
+      a[i] = i;
+      b[i] = i;
+    }
+  f1 (a.begin () + 10, a.begin () + 1990);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (a.begin () + 0, a.begin () + 1999);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (a.begin () + 20, a.begin () + 1837);
+  check (i >= 20 && i <= 1837);
+  f4<int> (a.begin () + 0, a.begin () + 30);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (a.begin () + 0, a.begin () + 100);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (a.begin () + 10, a.begin () + 110);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (std::vector<int>::const_iterator (), a.begin () + 12,
+        a.begin () + 1800);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (a.begin () + 14, a.begin () + 1803));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (a.begin () + 33, a.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (a.begin () + 1939, a.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::vector<int>::const_iterator > (a.begin () + 16, a.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::vector<int>::const_iterator > (a.begin () + 1761, a.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::vector<int>::const_iterator > (a.begin () + 1,
+                                               a.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f14 (a.begin () + 0, a.begin () + 1999) != a.begin () + 1998)
+    std::abort ();
+  check (i < 1998 && (i & 1) == 0);
+  if (f15<int> (a.begin () + 0, a.begin () + 30) != a.begin () + 40)
+    std::abort ();
+  check (i > 40 && i <= 2000 - 64);
+  if (f16<6> (std::vector<int>::const_iterator (), a.begin () + 12,
+             a.begin () + 1800) != a.begin () + 1814)
+    std::abort ();
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  if (f17<121> (J<int> (a.begin () + 14, a.begin () + 1803)) != a.begin () + 
1926)
+    std::abort ();
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  if (f18<int, -7> (a.begin () + 1939, a.begin () + 17) != a.begin () + 14)
+    std::abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<std::vector<int>::const_iterator > (a.begin () + 16, a.begin () + 
1981)
+      != a.begin () + 1984)
+    std::abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<std::vector<int>::const_iterator > (a.begin () + 1761, a.begin () + 
37)
+      != a.begin () + 37)
+    std::abort ();
+  check (i > 37 && i <= 1761);
+  f9<long, 7> (b.begin () + 33, b.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (b.begin () + 1939, b.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::vector<long>::const_iterator > (b.begin () + 16, b.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::vector<long>::const_iterator > (b.begin () + 1761, b.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::vector<long>::const_iterator > (b.begin () + 1,
+                                                b.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f18<long, -7> (b.begin () + 1939, b.begin () + 17) != b.begin () + 14)
+    std::abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<std::vector<long>::const_iterator > (b.begin () + 16, b.begin () + 
1981)
+      != b.begin () + 1984)
+    std::abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<std::vector<long>::const_iterator > (b.begin () + 1761, b.begin () + 
37)
+      != b.begin () + 37)
+    std::abort ();
+  check (i > 37 && i <= 1761);
+}
--- libgomp/testsuite/libgomp.c++/taskloop-8.C.jj       2015-06-23 
15:38:19.107160655 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-8.C  2015-06-23 15:40:44.694941712 
+0200
@@ -0,0 +1,250 @@
+// { dg-do run }
+
+#include <string>
+#include <cstdlib>
+
+template <typename T>
+class J
+{
+public:
+  typedef typename std::basic_string<T>::iterator iterator;
+  J(const iterator &x, const iterator &y) : b (x), e (y) {}
+  const iterator &begin ();
+  const iterator &end ();
+private:
+  iterator b, e;
+};
+
+template <typename T>
+const typename std::basic_string<T>::iterator &J<T>::begin () { return b; }
+template <typename T>
+const typename std::basic_string<T>::iterator &J<T>::end () { return e; }
+
+template <typename T>
+void
+baz (T &i)
+{
+  if (*i < L'a' || *i >= L'a' + 2000)
+    std::abort ();
+  (*i)++;
+}
+
+void
+f1 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x + 2000 - 64;
+       i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x + 2000 - 64;
+       i > y + 10; i = i - 12 + 2)
+    {
+      std::basic_string<wchar_t>::iterator j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (std::basic_string<wchar_t>::iterator i,
+    const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <wchar_t N>
+void
+f8 (J<wchar_t> j)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const typename std::basic_string<T>::iterator &x,
+    const typename std::basic_string<T>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (typename std::basic_string<T>::iterator i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const typename std::basic_string<T>::iterator &x,
+     const typename std::basic_string<T>::iterator &y)
+{
+  typename std::basic_string<T>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  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 single nowait
+#pragma omp taskloop nogroup
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop private(i)
+  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
+#pragma omp single
+#pragma omp taskloop
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)                       \
+    if (expr)                                          \
+      {                                                        \
+       if (a[i] != L'a' + i + 1)                       \
+         std::abort ();                                \
+       a[i] = L'a' + i;                                \
+      }                                                        \
+    else if (a[i] != L'a' + i)                         \
+      std::abort ()
+
+int
+main ()
+{
+  std::basic_string<wchar_t> a = L"";
+  for (int i = 0; i < 2000; i++)
+    a += L'a' + i;
+  f1 (a.begin () + 10, a.begin () + 1990);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (a.begin () + 0, a.begin () + 1999);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (a.begin () + 20, a.begin () + 1837);
+  check (i >= 20 && i <= 1837);
+  f4<int> (a.begin () + 0, a.begin () + 30);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (a.begin () + 0, a.begin () + 100);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (a.begin () + 10, a.begin () + 110);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (std::basic_string<wchar_t>::iterator (), a.begin () + 12,
+        a.begin () + 1800);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<wchar_t> (a.begin () + 14, a.begin () + 1803));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<wchar_t, 7> (a.begin () + 33, a.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<wchar_t, -7> (a.begin () + 1939, a.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::basic_string<wchar_t>::iterator > (a.begin () + 16,
+                                             a.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::basic_string<wchar_t>::iterator > (a.begin () + 1761,
+                                             a.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::basic_string<wchar_t>::iterator > (a.begin () + 1,
+                                                   a.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+}
--- libgomp/testsuite/libgomp.c++/taskloop-9.C.jj       2015-06-23 
15:41:50.575937601 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-9.C  2015-06-23 15:47:27.416900471 
+0200
@@ -0,0 +1,323 @@
+// { 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 single
+  #pragma omp taskloop lastprivate (i)
+    for (i = x; i < y - 1; ++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
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x; i < y - 1; i = 1 - 6 + 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 single
+#pragma omp taskloop lastprivate (i)
+    for (i = x + 1000 - 64; i <= y - 10; i++)
+      baz (i);
+  return i;
+}
+
+template <typename T>
+I<int>
+f4 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop 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
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x; i > y + T (6); 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
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x - T (7); i > y; i -= T (2))
+    baz (i);
+  return I<int> (i);
+}
+
+template <int N>
+I<int>
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop 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 single
+  #pragma omp taskloop lastprivate (i)
+    for (i = j.begin (); i <= j.end () + N; i += 2)
+      baz (i);
+  return i;
+}
+
+I<int> i9;
+
+template <long N>
+I<int> &
+f9 (J<int> j)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i9)
+  for (i9 = j.begin () + N; 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
+#pragma omp single
+#pragma omp taskloop 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 single
+  #pragma omp taskloop lastprivate (i)
+  for (i = x + U (2); i <= y + U (1); i = U (2) + U (3) + i)
+    baz (i);
+  return T (i);
+}
+
+template <typename T>
+T
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop 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[1873]) != 1875)
+    abort ();
+  check (i >= 10 && i < 1872);
+  if (*f2 (&a[0], &a[1998]) != 1998)
+    abort ();
+  check (i < 1997 && (i & 1) == 0);
+  if (*f3<int> (&a[10], &a[1971]) != 1962)
+    abort ();
+  check (i >= 946 && i <= 1961);
+  if (*f4<int> (&a[0], &a[30]) != 40)
+    abort ();
+  check (i > 40 && i <= 2000 - 64);
+  if (*f5<short> (&a[1931], &a[17]) != 23)
+    abort ();
+  check (i > 23 && i <= 1931);
+  if (*f6<long> (&a[1931], &a[17]) != 16)
+    abort ();
+  check (i > 17 && i <= 1924 && (i & 1) == 0);
+  if (*f7<6> (I<int> (), &a[12], &a[1800]) != 1814)
+    abort ();
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  if (*f8<121> (J<int> (&a[14], &a[1803])) != 1926)
+    abort ();
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  if (*f9<-3L> (J<int> (&a[27], &a[1761])) != 1767)
+    abort ();
+  check (i >= 24 && i <= 1764 && (i % 3) == 0);
+  if (*f10<int, -7> (&a[1939], &a[17]) != 14)
+    abort ();
+  check (i >= 21 && i <= 1939 && i % 7 == 0);
+  if (*f11<I<int>, short> (I<int> (), &a[71], &a[1941]) != 1943)
+    abort ();
+  check (i >= 73 && i <= 1938 && (i - 73) % 5 == 0);
+  if (*f12<I<int> > (&a[1761], &a[37]) != 37)
+    abort ();
+  check (i > 37 && i <= 1761);
+  if (*f10<long, -7> (&b[1939], &b[17]) != 14)
+    abort ();
+  check (i >= 21 && i <= 1939 && i % 7 == 0);
+  if (*f11<I<long>, short> (I<long> (), &b[71], &b[1941]) != 1943)
+    abort ();
+  check (i >= 73 && i <= 1938 && (i - 73) % 5 == 0);
+  if (*f12<I<long> > (&b[1761], &b[37]) != 37)
+    abort ();
+  check (i > 37 && i <= 1761);
+}

        Jakub

Reply via email to