This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp5] Support OpenMP 5.0 iterators in depend clauses


Hi!

The following patch adds support for depend clause iterators.

Tested on x86_64-linux, committed to gomp-5_0-branch.

2018-06-13  Jakub Jelinek  <jakub@redhat.com>

	* gimplify.c (gimplify_omp_depend): New function.
	(gimplify_scan_omp_clauses): Gimplify depend clauses with iterators.
	* omp-low.c (lower_depend_clauses): If OMP_CLAUSE_DEPEND_LAST is seen,
	assume lowering is done already and return early.  Set kind
	on artificial depend clause to OMP_CLAUSE_DEPEND_LAST.
	* tree-pretty-print.c (dump_omp_iterators): New function.
	(dump_omp_clause): Print iterators in depend clauses.  Print
	__internal__ for OMP_CLAUSE_DEPEND_LAST.
gcc/c/
	* c-parser.c (c_parser_omp_iterators): New function.
	(c_parser_omp_clause_depend): Parse iterator modifier and handle
	iterators.
	* c-typeck.c (handle_omp_array_sections): Handle depend clauses
	with iterators.
	(struct c_find_omp_var_s): New type.
	(c_find_omp_var_r): New function.
	(c_omp_finish_iterators): New function.
	(c_finish_omp_clauses): Handle depend clauses with iterators.
gcc/cp/
	* parser.c (cp_parser_omp_iterators): New function.
	(cp_parser_omp_clause_depend): Parse iterator modifier and handle
	iterators.
	* semantics.c (handle_omp_array_sections): Handle depend clauses
	with iterators.
	(cp_omp_finish_iterators): New function.
	(finish_omp_clauses): Handle depend clauses with iterators.
	* pt.c (tsubst_omp_clause_decl): Add iterators_cache argument.
	Adjust recursive calls.  Handle iterators.
	(tsubst_omp_clauses): Adjust tsubst_omp_clause_decl callers.
gcc/testsuite/
	* c-c++-common/gomp/depend-iterator-1.c: New test.
	* c-c++-common/gomp/depend-iterator-2.c: New test.
	* g++.dg/gomp/depend-iterator-1.C: New test.
	* g++.dg/gomp/depend-iterator-2.C: New test.
libgomp/
	* testsuite/libgomp.c-c++-common/depend-iterator-1.c: New test.
	* testsuite/libgomp.c++/depend-iterator-1.C: New test.

--- gcc/gimplify.c.jj	2018-06-05 15:00:56.217957674 +0200
+++ gcc/gimplify.c	2018-06-12 11:45:41.817981609 +0200
@@ -7556,6 +7556,368 @@ find_decl_expr (tree *tp, int *walk_subt
   return NULL_TREE;
 }
 
+/* If *LIST_P contains any OpenMP depend clauses with iterators,
+   lower all the depend clauses by populating corresponding depend
+   array.  Returns 0 if there are no such depend clauses, or
+   2 if all depend clauses should be removed, 1 otherwise.  */
+
+static int
+gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
+{
+  tree c;
+  gimple *g;
+  size_t n[2] = { 0, 0 };
+  tree counts[2] = { NULL_TREE, NULL_TREE };
+  tree last_iter = NULL_TREE, last_count = NULL_TREE;
+  size_t i;
+  location_t first_loc = UNKNOWN_LOCATION;
+
+  for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
+    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+      {
+	switch (OMP_CLAUSE_DEPEND_KIND (c))
+	  {
+	  case OMP_CLAUSE_DEPEND_IN:
+	    i = 0;
+	    break;
+	  case OMP_CLAUSE_DEPEND_OUT:
+	  case OMP_CLAUSE_DEPEND_INOUT:
+	  case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+	    i = 1;
+	    break;
+	  case OMP_CLAUSE_DEPEND_SOURCE:
+	  case OMP_CLAUSE_DEPEND_SINK:
+	    continue;
+	  default:
+	    gcc_unreachable ();
+	  }
+	tree t = OMP_CLAUSE_DECL (c);
+	if (first_loc == UNKNOWN_LOCATION)
+	  first_loc = OMP_CLAUSE_LOCATION (c);
+	if (TREE_CODE (t) == TREE_LIST
+	    && TREE_PURPOSE (t)
+	    && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+	  {
+	    if (TREE_PURPOSE (t) != last_iter)
+	      {
+		tree tcnt = size_one_node;
+		for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
+		  {
+		    if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
+				       is_gimple_val, fb_rvalue) == GS_ERROR
+			|| gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
+					  is_gimple_val, fb_rvalue) == GS_ERROR
+			|| (gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
+					   is_gimple_val, fb_rvalue)
+			    == GS_ERROR))
+		      return 2;
+		    tree var = TREE_VEC_ELT (it, 0);
+		    tree begin = TREE_VEC_ELT (it, 1);
+		    tree end = TREE_VEC_ELT (it, 2);
+		    tree step = TREE_VEC_ELT (it, 3);
+		    tree type = TREE_TYPE (var);
+		    tree stype = TREE_TYPE (step);
+		    location_t loc = DECL_SOURCE_LOCATION (var);
+		    tree endmbegin;
+		    /* Compute count for this iterator as
+		       step > 0
+		       ? (begin < end ? (end - begin + (step - 1)) / step : 0)
+		       : (begin > end ? (end - begin + (step + 1)) / step : 0)
+		       and compute product of those for the entire depend
+		       clause.  */
+		    if (POINTER_TYPE_P (type))
+		      endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR,
+						   stype, end, begin);
+		    else
+		      endmbegin = fold_build2_loc (loc, MINUS_EXPR, type,
+						   end, begin);
+		    tree stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype,
+						   step,
+						   build_int_cst (stype, 1));
+		    tree stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
+						   build_int_cst (stype, 1));
+		    tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
+						unshare_expr (endmbegin),
+						stepm1);
+		    pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype,
+					   pos, step);
+		    tree neg = fold_build2_loc (loc, PLUS_EXPR, stype,
+						endmbegin, stepp1);
+		    neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype,
+					   neg, step);
+		    tree cond = fold_build2_loc (loc, LT_EXPR,
+						 boolean_type_node,
+						 begin, end);
+		    pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
+					   build_int_cst (stype, 0));
+		    cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node,
+					    end, begin);
+		    neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
+					   build_int_cst (stype, 0));
+		    cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
+					    step, build_int_cst (stype, 0));
+		    tree cnt = fold_build3_loc (loc, COND_EXPR, stype,
+						cond, pos, neg);
+		    cnt = fold_convert_loc (loc, sizetype, cnt);
+		    if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
+				       fb_rvalue) == GS_ERROR)
+		      return 2;
+		    tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
+		  }
+		if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val,
+				   fb_rvalue) == GS_ERROR)
+		  return 2;
+		last_iter = TREE_PURPOSE (t);
+		last_count = tcnt;
+	      }
+	    if (counts[i] == NULL_TREE)
+	      counts[i] = last_count;
+	    else
+	      counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
+					  PLUS_EXPR, counts[i], last_count);
+	  }
+	else
+	  n[i]++;
+      }
+  if (counts[0] == NULL_TREE && counts[1] == NULL_TREE)
+    return 0;
+  for (i = 0; i < 2; i++)
+    {
+      if (counts[i] == NULL_TREE)
+	counts[i] = size_zero_node;
+      if (n[i])
+	counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
+      if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
+			 fb_rvalue) == GS_ERROR)
+	return 2;
+    }
+
+  tree total = size_binop (PLUS_EXPR, counts[0], counts[1]);
+  if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
+      == GS_ERROR)
+    return 2;
+  tree totalp1 = size_binop (PLUS_EXPR, unshare_expr (total), size_int (1));
+  tree type = build_array_type (ptr_type_node, build_index_type (totalp1));
+  tree array = create_tmp_var_raw (type);
+  TREE_ADDRESSABLE (array) = 1;
+  if (TREE_CODE (totalp1) != INTEGER_CST)
+    {
+      if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
+	gimplify_type_sizes (TREE_TYPE (array), pre_p);
+      if (gimplify_omp_ctxp)
+	{
+	  struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+	  while (ctx
+		 && (ctx->region_type == ORT_WORKSHARE
+		     || ctx->region_type == ORT_SIMD
+		     || ctx->region_type == ORT_ACC))
+	    ctx = ctx->outer_context;
+	  if (ctx)
+	    omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
+	}
+      gimplify_vla_decl (array, pre_p);
+    }
+  else
+    gimple_add_tmp_var (array);
+  tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
+		   NULL_TREE);
+  tree tem = build2 (MODIFY_EXPR, void_type_node, r,
+		     fold_convert (ptr_type_node, total));
+  gimplify_and_add (tem, pre_p);
+  r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
+	      NULL_TREE);
+  tem = build2 (MODIFY_EXPR, void_type_node, r, counts[1]);
+  gimplify_and_add (tem, pre_p);
+
+  tree cnts[2];
+  for (i = 0; i < 2; i++)
+    {
+      cnts[i] = create_tmp_var (sizetype, NULL);
+      g = gimple_build_assign (cnts[i], i == 0 ? size_int (2)
+					: size_binop (PLUS_EXPR, counts[0],
+						      size_int (2)));
+      gimple_seq_add_stmt (pre_p, g);
+    }
+
+  last_iter = NULL_TREE;
+  tree last_bind = NULL_TREE;
+  tree *last_body = NULL;
+  for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
+    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+      {
+	switch (OMP_CLAUSE_DEPEND_KIND (c))
+	  {
+	  case OMP_CLAUSE_DEPEND_IN:
+	    i = 0;
+	    break;
+	  case OMP_CLAUSE_DEPEND_OUT:
+	  case OMP_CLAUSE_DEPEND_INOUT:
+	  case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+	    i = 1;
+	    break;
+	  case OMP_CLAUSE_DEPEND_SOURCE:
+	  case OMP_CLAUSE_DEPEND_SINK:
+	    continue;
+	  default:
+	    gcc_unreachable ();
+	  }
+	tree t = OMP_CLAUSE_DECL (c);
+	if (TREE_CODE (t) == TREE_LIST
+	    && TREE_PURPOSE (t)
+	    && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+	  {
+	    if (TREE_PURPOSE (t) != last_iter)
+	      {
+		if (last_bind)
+		  gimplify_and_add (last_bind, pre_p);
+		tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 4);
+		last_bind = build3 (BIND_EXPR, void_type_node,
+				    BLOCK_VARS (block), NULL, block);
+		TREE_SIDE_EFFECTS (last_bind) = 1;
+		SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
+		tree *p = &BIND_EXPR_BODY (last_bind);
+		for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
+		  {
+		    tree var = TREE_VEC_ELT (it, 0);
+		    tree begin = TREE_VEC_ELT (it, 1);
+		    tree end = TREE_VEC_ELT (it, 2);
+		    tree step = TREE_VEC_ELT (it, 3);
+		    tree type = TREE_TYPE (var);
+		    tree stype = TREE_TYPE (step);
+		    location_t loc = DECL_SOURCE_LOCATION (var);
+		    /* Emit:
+		       var = begin;
+		       goto cond_label;
+		       beg_label:
+		       ...
+		       var = var + step;
+		       cond_label:
+		       if (step > 0) {
+			 if (var < end) goto beg_label;
+		       } else {
+			 if (var > end) goto beg_label;
+		       }
+		       for each iterator, with inner iterators added to
+		       the ... above.  */
+		    tree beg_label = create_artificial_label (loc);
+		    tree cond_label = NULL_TREE;
+		    tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
+				      var, begin);
+		    append_to_statement_list_force (tem, p);
+		    tem = build_and_jump (&cond_label);
+		    append_to_statement_list_force (tem, p);
+		    tem = build1 (LABEL_EXPR, void_type_node, beg_label);
+		    append_to_statement_list (tem, p);
+		    tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
+					NULL_TREE, NULL_TREE);
+		    TREE_SIDE_EFFECTS (bind) = 1;
+		    SET_EXPR_LOCATION (bind, loc);
+		    append_to_statement_list_force (bind, p);
+		    if (POINTER_TYPE_P (type))
+		      tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
+					var, fold_convert_loc (loc, sizetype,
+							       step));
+		    else
+		      tem = build2_loc (loc, PLUS_EXPR, type, var, step);
+		    tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
+				      var, tem);
+		    append_to_statement_list_force (tem, p);
+		    tem = build1 (LABEL_EXPR, void_type_node, cond_label);
+		    append_to_statement_list (tem, p);
+		    tree cond = fold_build2_loc (loc, LT_EXPR,
+						 boolean_type_node,
+						 var, end);
+		    tree pos
+		      = fold_build3_loc (loc, COND_EXPR, void_type_node,
+					 cond, build_and_jump (&beg_label),
+					 void_node);
+		    cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
+					    var, end);
+		    tree neg
+		      = fold_build3_loc (loc, COND_EXPR, void_type_node,
+					 cond, build_and_jump (&beg_label),
+					 void_node);
+		    cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
+					    step, build_int_cst (stype, 0));
+		    tem = fold_build3_loc (loc, COND_EXPR, void_type_node,
+					   cond, pos, neg);
+		    append_to_statement_list_force (tem, p);
+		    p = &BIND_EXPR_BODY (bind);
+		  }
+		last_body = p;
+	      }
+	    last_iter = TREE_PURPOSE (t);
+	    if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
+	      {
+		append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
+					  0), last_body);
+		TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
+	      }
+	    if (error_operand_p (TREE_VALUE (t)))
+	      return 2;
+	    TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
+	    r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
+			NULL_TREE, NULL_TREE);
+	    tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+			      void_type_node, r, TREE_VALUE (t));
+	    append_to_statement_list_force (tem, last_body);
+	    tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+			      void_type_node, cnts[i],
+			      size_binop (PLUS_EXPR, cnts[i], size_int (1)));
+	    append_to_statement_list_force (tem, last_body);
+	    TREE_VALUE (t) = null_pointer_node;
+	  }
+	else
+	  {
+	    if (last_bind)
+	      {
+		gimplify_and_add (last_bind, pre_p);
+		last_bind = NULL_TREE;
+	      }
+	    if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
+	      {
+		gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
+			       NULL, is_gimple_val, fb_rvalue);
+		OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
+	      }
+	    if (error_operand_p (OMP_CLAUSE_DECL (c)))
+	      return 2;
+	    OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
+	    if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
+			       is_gimple_val, fb_rvalue) == GS_ERROR)
+	      return 2;
+	    r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
+			NULL_TREE, NULL_TREE);
+	    tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
+	    gimplify_and_add (tem, pre_p);
+	    g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR, cnts[i],
+							  size_int (1)));
+	    gimple_seq_add_stmt (pre_p, g);
+	  }
+      }
+  if (last_bind)
+    gimplify_and_add (last_bind, pre_p);
+  tree cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
+			  size_binop_loc (first_loc, PLUS_EXPR, counts[0],
+					  size_int (2)));
+  cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
+		     build2_loc (first_loc, NE_EXPR, boolean_type_node,
+				 cnts[1],
+				 size_binop_loc (first_loc, PLUS_EXPR,
+						 totalp1, size_int (1))));
+  tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
+		    build_call_expr_loc (first_loc,
+					 builtin_decl_explicit (BUILT_IN_TRAP),
+					 0), void_node);
+  gimplify_and_add (tem, pre_p);
+  c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
+  OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
+  OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
+  OMP_CLAUSE_CHAIN (c) = *list_p;
+  *list_p = c;
+  return 1;
+}
+
 /* Scan the OMP clauses in *LIST_P, installing mappings into a new
    and previous omp contexts.  */
 
@@ -7568,6 +7930,7 @@ gimplify_scan_omp_clauses (tree *list_p,
   tree c;
   hash_map<tree, tree> *struct_map_to_clause = NULL;
   tree *prev_list_p = NULL;
+  int handled_depend_iterators = -1;
 
   ctx = new_omp_context (region_type);
   outer_ctx = ctx->outer_context;
@@ -8330,6 +8693,14 @@ gimplify_scan_omp_clauses (tree *list_p,
 	    }
 	  else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
 	    break;
+	  if (handled_depend_iterators == -1)
+	    handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
+	  if (handled_depend_iterators)
+	    {
+	      if (handled_depend_iterators == 2)
+		remove = true;
+	      break;
+	    }
 	  if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
 	    {
 	      gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
--- gcc/omp-low.c.jj	2018-06-05 15:00:56.232957694 +0200
+++ gcc/omp-low.c	2018-06-08 12:12:34.377111135 +0200
@@ -7347,6 +7347,9 @@ lower_depend_clauses (tree *pclauses, gi
     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
       switch (OMP_CLAUSE_DEPEND_KIND (c))
 	{
+	case OMP_CLAUSE_DEPEND_LAST:
+	  /* Lowering already done at gimplification.  */
+	  return;
 	case OMP_CLAUSE_DEPEND_IN:
 	  n_in++;
 	  break;
@@ -7390,6 +7393,7 @@ lower_depend_clauses (tree *pclauses, gi
 	  }
     }
   c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
+  OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
   OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
   OMP_CLAUSE_CHAIN (c) = *pclauses;
   *pclauses = c;
--- gcc/tree-pretty-print.c.jj	2018-06-05 15:00:56.232957694 +0200
+++ gcc/tree-pretty-print.c	2018-06-08 10:57:43.223983430 +0200
@@ -382,6 +382,31 @@ dump_array_domain (pretty_printer *pp, t
 }
 
 
+/* Dump OpenMP iterators ITER.  */
+
+static void
+dump_omp_iterators (pretty_printer *pp, tree iter, int spc, dump_flags_t flags)
+{
+  pp_string (pp, "iterator(");
+  for (tree it = iter; it; it = TREE_CHAIN (it))
+    {
+      if (it != iter)
+	pp_string (pp, ", ");
+      dump_generic_node (pp, TREE_TYPE (TREE_VEC_ELT (it, 0)), spc, flags,
+			 false);
+      pp_space (pp);
+      dump_generic_node (pp, TREE_VEC_ELT (it, 0), spc, flags, false);
+      pp_equal (pp);
+      dump_generic_node (pp, TREE_VEC_ELT (it, 1), spc, flags, false);
+      pp_colon (pp);
+      dump_generic_node (pp, TREE_VEC_ELT (it, 2), spc, flags, false);
+      pp_colon (pp);
+      dump_generic_node (pp, TREE_VEC_ELT (it, 3), spc, flags, false);
+    }
+  pp_right_paren (pp);
+}
+
+
 /* Dump OpenMP clause CLAUSE.  PP, CLAUSE, SPC and FLAGS are as in
    dump_generic_node.  */
 
@@ -650,20 +675,23 @@ dump_omp_clause (pretty_printer *pp, tre
       switch (OMP_CLAUSE_DEPEND_KIND (clause))
 	{
 	case OMP_CLAUSE_DEPEND_IN:
-	  pp_string (pp, "in");
+	  name = "in";
 	  break;
 	case OMP_CLAUSE_DEPEND_OUT:
-	  pp_string (pp, "out");
+	  name = "out";
 	  break;
 	case OMP_CLAUSE_DEPEND_INOUT:
-	  pp_string (pp, "inout");
+	  name = "inout";
 	  break;
 	case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
-	  pp_string (pp, "mutexinoutset");
+	  name = "mutexinoutset";
 	  break;
 	case OMP_CLAUSE_DEPEND_SOURCE:
 	  pp_string (pp, "source)");
 	  return;
+	case OMP_CLAUSE_DEPEND_LAST:
+	  name = "__internal__";
+	  break;
 	case OMP_CLAUSE_DEPEND_SINK:
 	  pp_string (pp, "sink:");
 	  for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t))
@@ -689,10 +717,21 @@ dump_omp_clause (pretty_printer *pp, tre
 	default:
 	  gcc_unreachable ();
 	}
-      pp_colon (pp);
-      dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
-			 spc, flags, false);
-      pp_right_paren (pp);
+      {
+	tree t = OMP_CLAUSE_DECL (clause);
+	if (TREE_CODE (t) == TREE_LIST
+	    && TREE_PURPOSE (t)
+	    && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+	  {
+	    dump_omp_iterators (pp, TREE_PURPOSE (t), spc, flags);
+	    pp_colon (pp);
+	    t = TREE_VALUE (t);
+	  }
+	pp_string (pp, name);
+	pp_colon (pp);
+	dump_generic_node (pp, t, spc, flags, false);
+	pp_right_paren (pp);
+      }
       break;
 
     case OMP_CLAUSE_MAP:
--- gcc/c/c-parser.c.jj	2018-06-05 15:00:56.357957856 +0200
+++ gcc/c/c-parser.c	2018-06-13 13:07:02.194649345 +0200
@@ -13802,6 +13802,106 @@ c_parser_omp_clause_depend_sink (c_parse
   return u;
 }
 
+/* OpenMP 5.0:
+   iterators ( iterators-definition )
+
+   iterators-definition:
+     iterator-specifier
+     iterator-specifier , iterators-definition
+
+   iterator-specifier:
+     identifier = range-specification
+     iterator-type identifier = range-specification
+
+   range-specification:
+     begin : end
+     begin : end : step  */
+
+static tree
+c_parser_omp_iterators (c_parser *parser)
+{
+  tree ret = NULL_TREE, *last = &ret;
+  c_parser_consume_token (parser);
+
+  push_scope ();
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return error_mark_node;
+
+  do
+    {
+      tree iter_type = NULL_TREE, type_expr = NULL_TREE;
+      if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
+	{
+	  struct c_type_name *type = c_parser_type_name (parser);
+	  if (type != NULL)
+	    iter_type = groktypename (type, &type_expr, NULL);
+	}
+      if (iter_type == NULL_TREE)
+	iter_type = integer_type_node;
+
+      location_t loc = c_parser_peek_token (parser)->location;
+      if (!c_parser_next_token_is (parser, CPP_NAME))
+	{
+	  c_parser_error (parser, "expected identifier");
+	  break;
+	}
+
+      tree id = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+	break;
+
+      location_t eloc = c_parser_peek_token (parser)->location;
+      c_expr expr = c_parser_expr_no_commas (parser, NULL);
+      expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
+      tree begin = expr.value;
+
+      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+	break;
+
+      eloc = c_parser_peek_token (parser)->location;
+      expr = c_parser_expr_no_commas (parser, NULL);
+      expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
+      tree end = expr.value;
+
+      tree step = integer_one_node;
+      if (c_parser_next_token_is (parser, CPP_COLON))
+	{
+	  c_parser_consume_token (parser);
+	  eloc = c_parser_peek_token (parser)->location;
+	  expr = c_parser_expr_no_commas (parser, NULL);
+	  expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
+	  step = expr.value;
+	}
+
+      tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
+      DECL_ARTIFICIAL (iter_var) = 1;
+      DECL_CONTEXT (iter_var) = current_function_decl;
+      pushdecl (iter_var);
+
+      *last = make_tree_vec (5);
+      TREE_VEC_ELT (*last, 0) = iter_var;
+      TREE_VEC_ELT (*last, 1) = begin;
+      TREE_VEC_ELT (*last, 2) = end;
+      TREE_VEC_ELT (*last, 3) = step;
+      last = &TREE_CHAIN (*last);
+
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+	{
+	  c_parser_consume_token (parser);
+	  continue;
+	}
+      break;
+    }
+  while (1);
+
+  parens.skip_until_found_close (parser);
+  return ret;
+}
+
 /* OpenMP 4.0:
    depend ( depend-kind: variable-list )
 
@@ -13818,14 +13918,17 @@ c_parser_omp_clause_depend (c_parser *pa
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
   enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
-  tree nl, c;
+  tree nl, c, iterators = NULL_TREE;
 
   matching_parens parens;
   if (!parens.require_open (parser))
     return list;
 
-  if (c_parser_next_token_is (parser, CPP_NAME))
+  do
     {
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+	goto invalid_kind;
+
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
       if (strcmp ("in", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_IN;
@@ -13839,14 +13942,29 @@ c_parser_omp_clause_depend (c_parser *pa
 	kind = OMP_CLAUSE_DEPEND_SOURCE;
       else if (strcmp ("sink", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_SINK;
+      else if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
+	{
+	  iterators = c_parser_omp_iterators (parser);
+	  c_parser_require (parser, CPP_COLON, "expected %<:%>");
+	  continue;
+	}
       else
 	goto invalid_kind;
+      break;
     }
-  else
-    goto invalid_kind;
+  while (1);
 
   c_parser_consume_token (parser);
 
+  if (iterators
+      && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+    {
+      pop_scope ();
+      error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
+		kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+      iterators = NULL_TREE;
+    }
+
   if (kind == OMP_CLAUSE_DEPEND_SOURCE)
     {
       c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
@@ -13867,8 +13985,22 @@ c_parser_omp_clause_depend (c_parser *pa
       nl = c_parser_omp_variable_list (parser, clause_loc,
 				       OMP_CLAUSE_DEPEND, list);
 
+      if (iterators)
+	{
+	  tree block = pop_scope ();
+	  if (iterators == error_mark_node)
+	    iterators = NULL_TREE;
+	  else
+	    TREE_VEC_ELT (iterators, 4) = block;
+	}
+
       for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
-	OMP_CLAUSE_DEPEND_KIND (c) = kind;
+	{
+	  OMP_CLAUSE_DEPEND_KIND (c) = kind;
+	  if (iterators)
+	    OMP_CLAUSE_DECL (c)
+	      = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
+	}
     }
 
   parens.skip_until_found_close (parser);
@@ -13878,6 +14010,8 @@ c_parser_omp_clause_depend (c_parser *pa
   c_parser_error (parser, "invalid depend kind");
  resync_fail:
   parens.skip_until_found_close (parser);
+  if (iterators)
+    pop_scope ();
   return list;
 }
 
--- gcc/c/c-typeck.c.jj	2018-06-05 10:59:17.886728884 +0200
+++ gcc/c/c-typeck.c	2018-06-13 18:21:54.220430042 +0200
@@ -12747,7 +12747,13 @@ handle_omp_array_sections (tree c, enum
   bool maybe_zero_len = false;
   unsigned int first_non_one = 0;
   auto_vec<tree, 10> types;
-  tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+  tree *tp = &OMP_CLAUSE_DECL (c);
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+      && TREE_CODE (*tp) == TREE_LIST
+      && TREE_PURPOSE (*tp)
+      && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+    tp = &TREE_VALUE (*tp);
+  tree first = handle_omp_array_sections_1 (c, *tp, types,
 					    maybe_zero_len, first_non_one,
 					    ort);
   if (first == error_mark_node)
@@ -12756,7 +12762,7 @@ handle_omp_array_sections (tree c, enum
     return false;
   if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
     {
-      tree t = OMP_CLAUSE_DECL (c);
+      tree t = *tp;
       tree tem = NULL_TREE;
       /* Need to evaluate side effects in the length expressions
 	 if any.  */
@@ -12775,7 +12781,7 @@ handle_omp_array_sections (tree c, enum
       if (tem)
 	first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
       first = c_fully_fold (first, false, NULL, true);
-      OMP_CLAUSE_DECL (c) = first;
+      *tp = first;
     }
   else
     {
@@ -13038,6 +13044,162 @@ c_find_omp_placeholder_r (tree *tp, int
   return NULL_TREE;
 }
 
+/* Similarly, but also walk aggregate fields.  */
+
+struct c_find_omp_var_s { tree var; hash_set<tree> *pset; };
+
+static tree
+c_find_omp_var_r (tree *tp, int *, void *data)
+{
+  if (*tp == ((struct c_find_omp_var_s *) data)->var)
+    return *tp;
+  if (RECORD_OR_UNION_TYPE_P (*tp))
+    {
+      tree field;
+      hash_set<tree> *pset = ((struct c_find_omp_var_s *) data)->pset;
+
+      for (field = TYPE_FIELDS (*tp); field;
+	   field = DECL_CHAIN (field))
+	if (TREE_CODE (field) == FIELD_DECL)
+	  {
+	    tree ret = walk_tree (&DECL_FIELD_OFFSET (field),
+				  c_find_omp_var_r, data, pset);
+	    if (ret)
+	      return ret;
+	    ret = walk_tree (&DECL_SIZE (field), c_find_omp_var_r, data, pset);
+	    if (ret)
+	      return ret;
+	    ret = walk_tree (&DECL_SIZE_UNIT (field), c_find_omp_var_r, data,
+			     pset);
+	    if (ret)
+	      return ret;
+	    ret = walk_tree (&TREE_TYPE (field), c_find_omp_var_r, data, pset);
+	    if (ret)
+	      return ret;
+	  }
+    }
+  else if (INTEGRAL_TYPE_P (*tp))
+    return walk_tree (&TYPE_MAX_VALUE (*tp), c_find_omp_var_r, data,
+		      ((struct c_find_omp_var_s *) data)->pset);
+  return NULL_TREE;
+}
+
+/* Finish OpenMP iterators ITER.  Return true if they are errorneous
+   and clauses containing them should be removed.  */
+
+static bool
+c_omp_finish_iterators (tree iter)
+{
+  bool ret = false;
+  for (tree it = iter; it; it = TREE_CHAIN (it))
+    {
+      tree var = TREE_VEC_ELT (it, 0);
+      tree begin = TREE_VEC_ELT (it, 1);
+      tree end = TREE_VEC_ELT (it, 2);
+      tree step = TREE_VEC_ELT (it, 3);
+      tree type = TREE_TYPE (var);
+      location_t loc = DECL_SOURCE_LOCATION (var);
+      if (type == error_mark_node)
+	{
+	  ret = true;
+	  continue;
+	}
+      if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+	{
+	  error_at (loc, "iterator %qD has neither integral nor pointer type",
+		    var);
+	  ret = true;
+	  continue;
+	}
+      else if (TYPE_ATOMIC (type))
+	{
+	  error_at (loc, "iterator %qD has %<_Atomic%> qualified type", var);
+	  ret = true;
+	  continue;
+	}
+      else if (TYPE_READONLY (type))
+	{
+	  error_at (loc, "iterator %qD has const qualified type", var);
+	  ret = true;
+	  continue;
+	}
+
+      begin = c_fully_fold (build_c_cast (loc, type, begin), false, NULL);
+      end = c_fully_fold (build_c_cast (loc, type, end), false, NULL);
+      tree stype = POINTER_TYPE_P (type) ? sizetype : type;
+      step = c_fully_fold (build_c_cast (loc, stype, step), false, NULL);
+      if (POINTER_TYPE_P (type))
+	{
+	  begin = save_expr (begin);
+	  step = pointer_int_sum (loc, PLUS_EXPR, begin, step);
+	  step = fold_build2_loc (loc, MINUS_EXPR, sizetype,
+				  fold_convert (sizetype, step),
+				  fold_convert (sizetype, begin));
+	  step = fold_convert (ssizetype, step);
+	}
+      if (integer_zerop (step))
+	{
+	  error_at (loc, "iterator %qD has zero step", var);
+	  ret = true;
+	  continue;
+	}
+
+      if (begin == error_mark_node
+	  || end == error_mark_node
+	  || step == error_mark_node)
+	{
+	  ret = true;
+	  continue;
+	}
+      hash_set<tree> pset;
+      tree it2;
+      for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2))
+	{
+	  tree var2 = TREE_VEC_ELT (it2, 0);
+	  tree begin2 = TREE_VEC_ELT (it2, 1);
+	  tree end2 = TREE_VEC_ELT (it2, 2);
+	  tree step2 = TREE_VEC_ELT (it2, 3);
+	  tree type2 = TREE_TYPE (var2);
+	  location_t loc2 = DECL_SOURCE_LOCATION (var2);
+	  struct c_find_omp_var_s data = { var, &pset };
+	  if (walk_tree (&type2, c_find_omp_var_r, &data, &pset))
+	    {
+	      error_at (loc2,
+			"type of iterator %qD refers to outer iterator %qD",
+			var2, var);
+	      break;
+	    }
+	  else if (walk_tree (&begin2, c_find_omp_var_r, &data, &pset))
+	    {
+	      error_at (EXPR_LOC_OR_LOC (begin2, loc2),
+			"begin expression refers to outer iterator %qD", var);
+	      break;
+	    }
+	  else if (walk_tree (&end2, c_find_omp_var_r, &data, &pset))
+	    {
+	      error_at (EXPR_LOC_OR_LOC (end2, loc2),
+			"end expression refers to outer iterator %qD", var);
+	      break;
+	    }
+	  else if (walk_tree (&step2, c_find_omp_var_r, &data, &pset))
+	    {
+	      error_at (EXPR_LOC_OR_LOC (step2, loc2),
+			"step expression refers to outer iterator %qD", var);
+	      break;
+	    }
+	}
+      if (it2)
+	{
+	  ret = true;
+	  continue;
+	}
+      TREE_VEC_ELT (it, 1) = begin;
+      TREE_VEC_ELT (it, 2) = end;
+      TREE_VEC_ELT (it, 3) = step;
+    }
+  return ret;
+}
+
 /* For all elements of CLAUSES, validate them against their constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -13055,6 +13217,8 @@ c_finish_omp_clauses (tree clauses, enum
   bool ordered_seen = false;
   tree schedule_clause = NULL_TREE;
   bool oacc_async = false;
+  tree last_iterators = NULL_TREE;
+  bool last_iterators_remove = false;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13589,6 +13753,20 @@ c_finish_omp_clauses (tree clauses, enum
 		}
 	      break;
 	    }
+	  if (TREE_CODE (t) == TREE_LIST
+	      && TREE_PURPOSE (t)
+	      && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+	    {
+	      if (TREE_PURPOSE (t) != last_iterators)
+		last_iterators_remove
+		  = c_omp_finish_iterators (TREE_PURPOSE (t));
+	      last_iterators = TREE_PURPOSE (t);
+	      t = TREE_VALUE (t);
+	      if (last_iterators_remove)
+		t = error_mark_node;
+	    }
+	  else
+	    last_iterators = NULL_TREE;
 	  if (TREE_CODE (t) == TREE_LIST)
 	    {
 	      if (handle_omp_array_sections (c, ort))
--- gcc/cp/parser.c.jj	2018-06-04 18:17:54.995533519 +0200
+++ gcc/cp/parser.c	2018-06-13 16:26:27.294958834 +0200
@@ -33598,6 +33598,118 @@ cp_parser_omp_clause_depend_sink (cp_par
   return list;
 }
 
+/* OpenMP 5.0:
+   iterators ( iterators-definition )
+
+   iterators-definition:
+     iterator-specifier
+     iterator-specifier , iterators-definition
+
+   iterator-specifier:
+     identifier = range-specification
+     iterator-type identifier = range-specification
+
+   range-specification:
+     begin : end
+     begin : end : step  */
+
+static tree
+cp_parser_omp_iterators (cp_parser *parser)
+{
+  tree ret = NULL_TREE, *last = &ret;
+  cp_lexer_consume_token (parser->lexer);
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return error_mark_node;
+
+  bool saved_colon_corrects_to_scope_p
+    = parser->colon_corrects_to_scope_p;
+  bool saved_colon_doesnt_start_class_def_p
+    = parser->colon_doesnt_start_class_def_p;
+
+  do
+    {
+      tree iter_type;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+	  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_EQ))
+	iter_type = integer_type_node;
+      else
+	{
+	  const char *saved_message
+	    = parser->type_definition_forbidden_message;
+	  parser->type_definition_forbidden_message
+	    = G_("types may not be defined in iterator type");
+
+	  iter_type = cp_parser_type_id (parser);
+
+	  parser->type_definition_forbidden_message = saved_message;
+	}
+
+      location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+	{
+	  cp_parser_error (parser, "expected identifier");
+	  break;
+	}
+
+      tree id = cp_parser_identifier (parser);
+      if (id == error_mark_node)
+	break;
+
+      if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+	break;
+
+      parser->colon_corrects_to_scope_p = false;
+      parser->colon_doesnt_start_class_def_p = true;
+      tree begin = cp_parser_assignment_expression (parser);
+
+      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+	break;
+
+      tree end = cp_parser_assignment_expression (parser);
+
+      tree step = integer_one_node;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  step = cp_parser_assignment_expression (parser);
+	}
+
+      tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
+      DECL_ARTIFICIAL (iter_var) = 1;
+      DECL_CONTEXT (iter_var) = current_function_decl;
+      pushdecl (iter_var);
+
+      *last = make_tree_vec (5);
+      TREE_VEC_ELT (*last, 0) = iter_var;
+      TREE_VEC_ELT (*last, 1) = begin;
+      TREE_VEC_ELT (*last, 2) = end;
+      TREE_VEC_ELT (*last, 3) = step;
+      last = &TREE_CHAIN (*last);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  continue;
+	}
+      break;
+    }
+  while (1);
+
+  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+  parser->colon_doesnt_start_class_def_p
+    = saved_colon_doesnt_start_class_def_p;
+
+  if (!parens.require_close (parser))
+    cp_parser_skip_to_closing_parenthesis (parser,
+					   /*recovering=*/true,
+					   /*or_comma=*/false,
+					   /*consume_paren=*/true);
+
+  return ret;
+}
+
 /* OpenMP 4.0:
    depend ( depend-kind : variable-list )
 
@@ -33612,15 +33724,18 @@ cp_parser_omp_clause_depend_sink (cp_par
 static tree
 cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
 {
-  tree nlist, c;
+  tree nlist, c, iterators = NULL_TREE;
   enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
 
   matching_parens parens;
   if (!parens.require_open (parser))
     return list;
 
-  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+  do
     {
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+	goto invalid_kind;
+
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
 
@@ -33636,14 +33751,30 @@ cp_parser_omp_clause_depend (cp_parser *
 	kind = OMP_CLAUSE_DEPEND_SOURCE;
       else if (strcmp ("sink", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_SINK;
+      else if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
+	{
+	  begin_scope (sk_omp, NULL);
+	  iterators = cp_parser_omp_iterators (parser);
+	  cp_parser_require (parser, CPP_COLON, RT_COLON);
+	  continue;
+	}
       else
 	goto invalid_kind;
+      break;
     }
-  else
-    goto invalid_kind;
+  while (1);
 
   cp_lexer_consume_token (parser->lexer);
 
+  if (iterators
+      && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+    {
+      poplevel (0, 1, 0);
+      error_at (loc, "%<iterator%> modifier incompatible with %qs",
+		kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+      iterators = NULL_TREE;
+    }
+
   if (kind == OMP_CLAUSE_DEPEND_SOURCE)
     {
       c = build_omp_clause (loc, OMP_CLAUSE_DEPEND);
@@ -33667,14 +33798,30 @@ cp_parser_omp_clause_depend (cp_parser *
       nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND,
 					      list, NULL);
 
+      if (iterators)
+	{
+	  tree block = poplevel (1, 1, 0);
+	  if (iterators == error_mark_node)
+	    iterators = NULL_TREE;
+	  else
+	    TREE_VEC_ELT (iterators, 4) = block;
+	}
+
       for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
-	OMP_CLAUSE_DEPEND_KIND (c) = kind;
+	{
+	  OMP_CLAUSE_DEPEND_KIND (c) = kind;
+	  if (iterators)
+	    OMP_CLAUSE_DECL (c)
+	      = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
+	}
     }
   return nlist;
 
  invalid_kind:
   cp_parser_error (parser, "invalid depend kind");
  resync_fail:
+  if (iterators)
+    poplevel (0, 1, 0);
   cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
 					 /*or_comma=*/false,
 					 /*consume_paren=*/true);
--- gcc/cp/semantics.c.jj	2018-06-05 13:55:00.982594192 +0200
+++ gcc/cp/semantics.c	2018-06-13 19:25:03.003926735 +0200
@@ -4851,7 +4851,13 @@ handle_omp_array_sections (tree c, enum
   bool maybe_zero_len = false;
   unsigned int first_non_one = 0;
   auto_vec<tree, 10> types;
-  tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+  tree *tp = &OMP_CLAUSE_DECL (c);
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+      && TREE_CODE (*tp) == TREE_LIST
+      && TREE_PURPOSE (*tp)
+      && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+    tp = &TREE_VALUE (*tp);
+  tree first = handle_omp_array_sections_1 (c, *tp, types,
 					    maybe_zero_len, first_non_one,
 					    ort);
   if (first == error_mark_node)
@@ -4860,7 +4866,7 @@ handle_omp_array_sections (tree c, enum
     return false;
   if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
     {
-      tree t = OMP_CLAUSE_DECL (c);
+      tree t = *tp;
       tree tem = NULL_TREE;
       if (processing_template_decl)
 	return false;
@@ -4880,7 +4886,7 @@ handle_omp_array_sections (tree c, enum
 	}
       if (tem)
 	first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
-      OMP_CLAUSE_DECL (c) = first;
+      *tp = first;
     }
   else
     {
@@ -5842,6 +5848,125 @@ cp_finish_omp_clause_depend_sink (tree s
   return false;
 }
 
+/* Finish OpenMP iterators ITER.  Return true if they are errorneous
+   and clauses containing them should be removed.  */
+
+static bool
+cp_omp_finish_iterators (tree iter)
+{
+  bool ret = false;
+  for (tree it = iter; it; it = TREE_CHAIN (it))
+    {
+      tree var = TREE_VEC_ELT (it, 0);
+      tree begin = TREE_VEC_ELT (it, 1);
+      tree end = TREE_VEC_ELT (it, 2);
+      tree step = TREE_VEC_ELT (it, 3);
+      tree type = TREE_TYPE (var);
+      location_t loc = DECL_SOURCE_LOCATION (var);
+      if (type == error_mark_node)
+	{
+	  ret = true;
+	  continue;
+	}
+      if (type_dependent_expression_p (var))
+	continue;
+      if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+	{
+	  error_at (loc, "iterator %qD has neither integral nor pointer type",
+		    var);
+	  ret = true;
+	  continue;
+	}
+      else if (TYPE_READONLY (type))
+	{
+	  error_at (loc, "iterator %qD has const qualified type", var);
+	  ret = true;
+	  continue;
+	}
+
+      begin = mark_rvalue_use (begin);
+      end = mark_rvalue_use (end);
+      step = mark_rvalue_use (step);
+      begin = cp_build_c_cast (type, begin, tf_warning_or_error);
+      end = cp_build_c_cast (type, end, tf_warning_or_error);
+      tree stype = POINTER_TYPE_P (type) ? sizetype : type;
+      step = cp_build_c_cast (stype, step, tf_warning_or_error);
+      if (POINTER_TYPE_P (type) && !processing_template_decl)
+	{
+	  begin = save_expr (begin);
+	  step = pointer_int_sum (loc, PLUS_EXPR, begin, step);
+	  step = fold_build2_loc (loc, MINUS_EXPR, sizetype,
+				  fold_convert (sizetype, step),
+				  fold_convert (sizetype, begin));
+	  step = fold_convert (ssizetype, step);
+	}
+      if (!processing_template_decl)
+	{
+	  begin = maybe_constant_value (begin);
+	  end = maybe_constant_value (end);
+	  step = maybe_constant_value (step);
+	}
+      if (integer_zerop (step))
+	{
+	  error_at (loc, "iterator %qD has zero step", var);
+	  ret = true;
+	  continue;
+	}
+
+      if (begin == error_mark_node
+	  || end == error_mark_node
+	  || step == error_mark_node)
+	{
+	  ret = true;
+	  continue;
+	}
+
+      if (!processing_template_decl)
+	{
+	  begin = fold_build_cleanup_point_expr (TREE_TYPE (begin), begin);
+	  end = fold_build_cleanup_point_expr (TREE_TYPE (end), end);
+	  step = fold_build_cleanup_point_expr (TREE_TYPE (step), step);
+	}
+      hash_set<tree> pset;
+      tree it2;
+      for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2))
+	{
+	  tree var2 = TREE_VEC_ELT (it2, 0);
+	  tree begin2 = TREE_VEC_ELT (it2, 1);
+	  tree end2 = TREE_VEC_ELT (it2, 2);
+	  tree step2 = TREE_VEC_ELT (it2, 3);
+	  location_t loc2 = DECL_SOURCE_LOCATION (var2);
+	  if (cp_walk_tree (&begin2, find_omp_placeholder_r, var, &pset))
+	    {
+	      error_at (EXPR_LOC_OR_LOC (begin2, loc2),
+			"begin expression refers to outer iterator %qD", var);
+	      break;
+	    }
+	  else if (cp_walk_tree (&end2, find_omp_placeholder_r, var, &pset))
+	    {
+	      error_at (EXPR_LOC_OR_LOC (end2, loc2),
+			"end expression refers to outer iterator %qD", var);
+	      break;
+	    }
+	  else if (cp_walk_tree (&step2, find_omp_placeholder_r, var, &pset))
+	    {
+	      error_at (EXPR_LOC_OR_LOC (step2, loc2),
+			"step expression refers to outer iterator %qD", var);
+	      break;
+	    }
+	}
+      if (it2)
+	{
+	  ret = true;
+	  continue;
+	}
+      TREE_VEC_ELT (it, 1) = begin;
+      TREE_VEC_ELT (it, 2) = end;
+      TREE_VEC_ELT (it, 3) = step;
+    }
+  return ret;
+}
+
 /* For all elements of CLAUSES, validate them vs OpenMP constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -5856,6 +5981,8 @@ finish_omp_clauses (tree clauses, enum c
   bool copyprivate_seen = false;
   bool ordered_seen = false;
   bool oacc_async = false;
+  tree last_iterators = NULL_TREE;
+  bool last_iterators_remove = false;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -6565,7 +6692,7 @@ finish_omp_clauses (tree clauses, enum c
 	  else
 	    {
 	      t = mark_rvalue_use (t);
-	      if (!processing_template_decl)
+ 	      if (!processing_template_decl)
 		t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
 	      OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
 	    }
@@ -6642,6 +6769,8 @@ finish_omp_clauses (tree clauses, enum c
 				"be positive constant integer expression");
 		      remove = true;
 		    }
+		  else
+		    t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
 		}
 	      OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t;
 	    }
@@ -6688,6 +6817,21 @@ finish_omp_clauses (tree clauses, enum c
 		remove = true;
 	      break;
 	    }
+	  if (TREE_CODE (t) == TREE_LIST
+	      && TREE_PURPOSE (t)
+	      && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+	    {
+	      if (TREE_PURPOSE (t) != last_iterators)
+		last_iterators_remove
+		  = cp_omp_finish_iterators (TREE_PURPOSE (t));
+	      last_iterators = TREE_PURPOSE (t);
+	      t = TREE_VALUE (t);
+	      if (last_iterators_remove)
+		t = error_mark_node;
+	    }
+	  else
+	    last_iterators = NULL_TREE;
+
 	  if (TREE_CODE (t) == TREE_LIST)
 	    {
 	      if (handle_omp_array_sections (c, ort))
@@ -6703,7 +6847,7 @@ finish_omp_clauses (tree clauses, enum c
 			" clauses");
 	      remove = true;
 	    }
-          else if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+	  else if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
 	    break;
 	  else if (!lvalue_p (t))
 	    {
--- gcc/cp/pt.c.jj	2018-06-04 18:17:53.478531126 +0200
+++ gcc/cp/pt.c	2018-06-13 17:33:22.060761294 +0200
@@ -15941,11 +15941,49 @@ tsubst_copy (tree t, tree args, tsubst_f
 
 static tree
 tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
-			tree in_decl)
+			tree in_decl, tree *iterator_cache)
 {
   if (decl == NULL_TREE)
     return NULL_TREE;
 
+  /* Handle OpenMP iterators.  */
+  if (TREE_CODE (decl) == TREE_LIST
+      && TREE_PURPOSE (decl)
+      && TREE_CODE (TREE_PURPOSE (decl)) == TREE_VEC)
+    {
+      tree ret;
+      if (iterator_cache[0] == TREE_PURPOSE (decl))
+	ret = iterator_cache[1];
+      else
+	{
+	  tree *tp = &ret;
+	  begin_scope (sk_omp, NULL);
+	  for (tree it = TREE_PURPOSE (decl); it; it = TREE_CHAIN (it))
+	    {
+	      *tp = copy_node (it);
+	      TREE_VEC_ELT (*tp, 0)
+		= tsubst_decl (TREE_VEC_ELT (it, 0), args, complain);
+	      TREE_VEC_ELT (*tp, 1)
+		= tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl,
+			       /*integral_constant_expression_p=*/false);
+	      TREE_VEC_ELT (*tp, 2)
+		= tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl,
+			       /*integral_constant_expression_p=*/false);
+	      TREE_VEC_ELT (*tp, 3)
+		= tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl,
+			       /*integral_constant_expression_p=*/false);
+	      TREE_CHAIN (*tp) = NULL_TREE;
+	      tp = &TREE_CHAIN (*tp);
+	    }
+	  TREE_VEC_ELT (ret, 4) = poplevel (1, 1, 0);
+	  iterator_cache[0] = TREE_PURPOSE (decl);
+	  iterator_cache[1] = ret;
+	}
+      return build_tree_list (ret, tsubst_omp_clause_decl (TREE_VALUE (decl),
+							   args, complain,
+							   in_decl, NULL));
+    }
+
   /* Handle an OpenMP array section represented as a TREE_LIST (or
      OMP_CLAUSE_DEPEND_KIND).  An OMP_CLAUSE_DEPEND (with a depend
      kind of OMP_CLAUSE_DEPEND_SINK) can also be represented as a
@@ -15960,7 +15998,7 @@ tsubst_omp_clause_decl (tree decl, tree
       tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl,
 				 /*integral_constant_expression_p=*/false);
       tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain,
-					   in_decl);
+					   in_decl, NULL);
       if (TREE_PURPOSE (decl) == low_bound
 	  && TREE_VALUE (decl) == length
 	  && TREE_CHAIN (decl) == chain)
@@ -15988,6 +16026,7 @@ tsubst_omp_clauses (tree clauses, enum c
 {
   tree new_clauses = NULL_TREE, nc, oc;
   tree linear_no_step = NULL_TREE;
+  tree iterator_cache[2] = { NULL_TREE, NULL_TREE };
 
   for (oc = clauses; oc ; oc = OMP_CLAUSE_CHAIN (oc))
     {
@@ -16022,7 +16061,7 @@ tsubst_omp_clauses (tree clauses, enum c
 	case OMP_CLAUSE_IS_DEVICE_PTR:
 	  OMP_CLAUSE_DECL (nc)
 	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
-				      in_decl);
+				      in_decl, iterator_cache);
 	  break;
 	case OMP_CLAUSE_TILE:
 	case OMP_CLAUSE_IF:
@@ -16070,13 +16109,13 @@ tsubst_omp_clauses (tree clauses, enum c
 	    }
 	  OMP_CLAUSE_DECL (nc)
 	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
-				      in_decl);
+				      in_decl, NULL);
 	  break;
 	case OMP_CLAUSE_GANG:
 	case OMP_CLAUSE_ALIGNED:
 	  OMP_CLAUSE_DECL (nc)
 	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
-				      in_decl);
+				      in_decl, NULL);
 	  OMP_CLAUSE_OPERAND (nc, 1)
 	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
 			   in_decl, /*integral_constant_expression_p=*/false);
@@ -16084,7 +16123,7 @@ tsubst_omp_clauses (tree clauses, enum c
 	case OMP_CLAUSE_LINEAR:
 	  OMP_CLAUSE_DECL (nc)
 	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
-				      in_decl);
+				      in_decl, NULL);
 	  if (OMP_CLAUSE_LINEAR_STEP (oc) == NULL_TREE)
 	    {
 	      gcc_assert (!linear_no_step);
@@ -16093,7 +16132,7 @@ tsubst_omp_clauses (tree clauses, enum c
 	  else if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (oc))
 	    OMP_CLAUSE_LINEAR_STEP (nc)
 	      = tsubst_omp_clause_decl (OMP_CLAUSE_LINEAR_STEP (oc), args,
-					complain, in_decl);
+					complain, in_decl, NULL);
 	  else
 	    OMP_CLAUSE_LINEAR_STEP (nc)
 	      = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args, complain,
--- gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c.jj	2018-06-12 13:02:05.236081056 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c	2018-06-12 13:35:30.116318942 +0200
@@ -0,0 +1,75 @@
+int arr[64], arr2[64];
+struct S { int a[4]; } k;
+short arr4[4];
+volatile int v;
+#define TEST_EQ(x,y) ({ int o[x == y ? 1 : -1]; 0; })
+
+void
+foo (unsigned char i, signed char j)
+{
+  #pragma omp task depend (iterator (j=6:2:-2) : out : \
+	arr[TEST_EQ (sizeof (j), sizeof (int)), \
+	    TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+	    TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+	arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+	depend(out: arr[0]) \
+	depend (iterator (long long i=__LONG_LONG_MAX__ - 4:__LONG_LONG_MAX__ - 2:2, \
+			  unsigned short j=~0U-16:~0U-8:3, \
+			  short *k=&arr4[1]:&arr4[2]:1) : in : \
+	arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+	    TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+	    TEST_EQ (sizeof (k), sizeof (short *)), \
+	    TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+	arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+	arr2[k - &arr4[0]]) \
+	depend(in : k)
+    v++;
+}
+
+void
+bar (unsigned char i, signed char j)
+{
+  int m = j;
+  int n = j + 2;
+  #pragma omp task depend (iterator (j=6:2:m) : out : \
+	arr[TEST_EQ (sizeof (j), sizeof (int)), \
+	    TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+	    TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+	arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+	depend(out: arr[0]) \
+	depend (iterator (long long i=__LONG_LONG_MAX__ - 4 - n:__LONG_LONG_MAX__ - 2:2, \
+			  unsigned short j=~0U-16:~0U-8-n:3, \
+			  short *k=&arr4[1]:&arr4[n + 2]:1) : in : \
+	arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+	    TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+	    TEST_EQ (sizeof (k), sizeof (short *)), \
+	    TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+	arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+	arr2[k - &arr4[0]:10]) \
+	depend(in : k)
+    v++;
+}
+
+void
+baz (void)
+{
+  #pragma omp parallel
+  #pragma omp master
+  {
+    #pragma omp task depend(iterator(unsigned long int k = 0 : 2) : inout : \
+	arr[TEST_EQ (sizeof (k), sizeof (unsigned long)), \
+	    TEST_EQ (((__typeof (k)) -1) < 0, 0), k]) \
+	depend(iterator(signed char s = -3 : -12 : -1) : out : \
+	arr[TEST_EQ (sizeof (s), sizeof (signed char)), \
+	    TEST_EQ (((__typeof (s)) -1) < 0, 1), s + 12])
+      v++;
+  }
+}
--- gcc/testsuite/c-c++-common/gomp/depend-iterator-2.c.jj	2018-06-12 14:29:21.653895079 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-iterator-2.c	2018-06-13 18:27:33.876741370 +0200
@@ -0,0 +1,91 @@
+int a, b[64];
+struct S { int c; } *d, *e;
+struct T;
+struct T *f, *g;
+int *h;
+
+void
+f1 (void)
+{
+  #pragma omp task depend (iterator : in : a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend (iterator (for = 0 : 2) : in : a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend (iterator (5 = 0 : 2) : in : a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend (iterator (i : 0 : 2) : in : a)	/* { dg-error "expected '='|name a type|expected" } */
+  ;
+  #pragma omp task depend (iterator (i = 0, 1 : 2) : in : a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend (iterator (i = (0, 1) : 2) : in : a)
+  ;
+  #pragma omp task depend (iterator (i = 0 : 1 : 2 : 3) : in : a)	/* { dg-error "expected '.'" } */
+  ;
+  #pragma omp task depend (iterator (i = 0 : 2, 3) : in : a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend (iterator (i = 0 : 10 : 2, 3) : in : a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a)	/* { dg-error "expected ':'|invalid depend kind" } */
+  ;
+  #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a)	/* { dg-error "invalid depend kind" } */
+  ;
+  #pragma omp task depend (iterator (i = 0:32) : in : b[i*2:2])
+  ;
+  #pragma omp task depend (iterator (struct S i = 0:1): in : a)		/* { dg-error "iterator 'i' has neither integral nor pointer type" } */
+  ;
+  #pragma omp task depend (iterator (void i = 0:1) : in : a)		/* { dg-error "iterator 'i' has neither integral nor pointer type" } */
+  ;
+  #pragma omp task depend (iterator (float f = 0.2:0.4) : in : a)	/* { dg-error "iterator 'f' has neither integral nor pointer type" } */
+  ;
+  #pragma omp task depend (iterator (struct S *p = d:e:2) : in : a)
+  ;
+  #pragma omp task depend (iterator (struct T *p = f:g) : in : a)	/* { dg-error "invalid use of" } */
+  ;
+  #pragma omp task depend (iterator (int i = 0:4, \
+				     struct U { int (*p)[i + 2]; } *p = 0:2) : in : a)	/* { dg-error "type of iterator 'p' refers to outer iterator 'i'" "" { target c } } */
+  ;									/* { dg-error "types may not be defined in iterator type|not an integer constant" "" { target c++ } .-1 } */
+  #pragma omp task depend (iterator (i = 0:4, j = i:16) : in : a)	/* { dg-error "begin expression refers to outer iterator 'i'" } */
+  ;
+  #pragma omp task depend (iterator (i = 0:4, j = 2:i:1) : in : a)	/* { dg-error "end expression refers to outer iterator 'i'" } */
+  ;
+  #pragma omp task depend (iterator (i = 0:4, j = 2:8:i) : in : a)	/* { dg-error "step expression refers to outer iterator 'i'" } */
+  ;
+  #pragma omp task depend (iterator (i = *d:2) : in : a)	/* { dg-error "aggregate value used where an integer was expected" "" { target c } } */
+  ;								/* { dg-error "invalid cast from type 'S' to type 'int'" "" { target c++ } .-1 } */
+  #pragma omp task depend (iterator (i = 2:*d:2) : in : a)	/* { dg-error "aggregate value used where an integer was expected" "" { target c } } */
+  ;								/* { dg-error "invalid cast from type 'S' to type 'int'" "" { target c++ } .-1 } */
+  #pragma omp task depend (iterator (i = 2:4:*d) : in : a)	/* { dg-error "aggregate value used where an integer was expected" "" { target c } } */
+  ;								/* { dg-error "invalid cast from type 'S' to type 'int'" "" { target c++ } .-1 } */
+								/* { dg-error "iterator 'i' has zero step" "" { target c } .-2 } */
+  #pragma omp task depend (iterator (i = 1.25:2.5:3.5) : in : a)
+  ;
+  #pragma omp task depend (iterator (int *p = 23 : h) : in : a)
+  ;
+  #pragma omp task depend (iterator (short i=1:3:0) : in : a)	/* { dg-error "iterator 'i' has zero step" } */
+  ;
+  #pragma omp task depend (iterator (i = 1 : 3 : 3 - 3) : in : a)	/* { dg-error "iterator 'i' has zero step" } */
+  ;
+  #pragma omp task depend (iterator (int *p = &b[6]:&b[9]:4 - 4) : in : a)	/* { dg-error "iterator 'p' has zero step" } */
+  ;
+  #pragma omp task depend (iterator (const int i = 0 : 2) : in : a)	/* { dg-error "const qualified" } */
+  ;
+  #pragma omp task depend (iterator (const long long unsigned i = 0 : 2) : in : a)	/* { dg-error "const qualified" } */
+  ;
+#if !defined (__cplusplus) && __STDC_VERSION__ >= 201112L
+  #pragma omp task depend (iterator (_Atomic unsigned i = 0 : 2) : in : a)	/* { dg-error "_Atomic" "" { target c } } */
+  ;
+#endif
+}
+
+void
+f2 (void)
+{
+  int i, j;
+  #pragma omp for ordered(2)
+  for (i = 0; i < 64; i++)
+    for (j = 0; j < 64; j++)
+      {
+      #pragma omp ordered depend (iterator (k=0:1) : sink: i - 1, j - 1)	/* { dg-error "'iterator' modifier incompatible with 'sink'" } */
+      #pragma omp ordered depend (iterator (int l = 0:2:3) : source)		/* { dg-error "'iterator' modifier incompatible with 'source'" } */
+      }
+}
--- gcc/testsuite/g++.dg/gomp/depend-iterator-1.C.jj	2018-06-13 18:29:02.828823024 +0200
+++ gcc/testsuite/g++.dg/gomp/depend-iterator-1.C	2018-06-13 18:36:35.959238977 +0200
@@ -0,0 +1,86 @@
+int arr[64], arr2[64];
+struct S { int a[4]; } k;
+short arr4[4];
+volatile int v;
+#define TEST_EQ(x,y) ({ int o[x == y ? 1 : -1]; 0; })
+
+template <typename T, typename U, typename V, typename W, int N>
+void
+foo (unsigned char i, signed char j)
+{
+  #pragma omp task depend (iterator (T j=6:N:-2) : out : \
+	arr[TEST_EQ (sizeof (j), sizeof (int)), \
+	    TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+	    TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+	arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+	depend(out: arr[0]) \
+	depend (iterator (U i=__LONG_LONG_MAX__ - 4:__LONG_LONG_MAX__ - N:N, \
+			  V j=~0U-16:~0U-8:3, \
+			  W *k=&arr4[1]:&arr4[2]:1) : in : \
+	arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+	    TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+	    TEST_EQ (sizeof (k), sizeof (short *)), \
+	    TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+	arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+	arr2[k - &arr4[0]]) \
+	depend(in : k)
+    v++;
+}
+
+template <typename U, typename W, int N>
+void
+bar (unsigned char i, signed char j)
+{
+  int m = j;
+  int n = j + 2;
+  #pragma omp task depend (iterator (j=N:2:m) : out : \
+	arr[TEST_EQ (sizeof (j), sizeof (int)), \
+	    TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+	    TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+	arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+	depend(out: arr[0]) \
+	depend (iterator (U i=__LONG_LONG_MAX__ - 4 - n:__LONG_LONG_MAX__ - 2:2, \
+			  unsigned short j=~0U-16:~0U-8-n:3, \
+			  W k=&arr4[N-5]:&arr4[n + 2]:1) : in : \
+	arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+	    TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+	    TEST_EQ (sizeof (k), sizeof (short *)), \
+	    TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+	arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+	     TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+	     TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+	arr2[k - &arr4[0]:10]) \
+	depend(in : k)
+    v++;
+}
+
+template <typename T, typename U, int N>
+void
+baz (void)
+{
+  #pragma omp parallel
+  #pragma omp master
+  {
+    #pragma omp task depend(iterator(T k = N : 2) : inout : \
+	arr[TEST_EQ (sizeof (k), sizeof (unsigned long)), \
+	    TEST_EQ (((__typeof (k)) -1) < N, 0), k]) \
+	depend(iterator(U s = -3 : -12 : -1 + N) : out : \
+	arr[TEST_EQ (sizeof (s), sizeof (signed char)), \
+	    TEST_EQ (((__typeof (s)) -1) < 0, 1), s + 12])
+      v++;
+  }
+}
+
+void
+test (void)
+{
+  foo <int, long long, unsigned short, short, 2> (0, 0);
+  bar <long long, short *, 6> (0, -2);
+  baz <unsigned long int, signed char, 0> ();
+}
--- gcc/testsuite/g++.dg/gomp/depend-iterator-2.C.jj	2018-06-13 18:59:57.212537261 +0200
+++ gcc/testsuite/g++.dg/gomp/depend-iterator-2.C	2018-06-13 19:15:06.993378812 +0200
@@ -0,0 +1,110 @@
+int a, b[64];
+struct S { int c; } *d, *e;
+struct T;
+struct T *f, *g;
+int *h;
+
+template <typename U, typename V, typename W, W N>
+void
+f1 ()
+{
+  #pragma omp task depend (iterator : in : a)	// { dg-error "expected" }
+  ;
+  #pragma omp task depend (iterator (for = 0 : 2) : in : a)	// { dg-error "expected" }
+  ;
+  #pragma omp task depend (iterator (5 = 0 : 2) : in : a)	// { dg-error "expected" }
+  ;
+  #pragma omp task depend (iterator (i : N : 2) : in : a)	// { dg-error "expected '='|name a type|expected" }
+  ;
+  #pragma omp task depend (iterator (i = 0, 1 : 2) : in : a)	// { dg-error "expected" }
+  ;
+  #pragma omp task depend (iterator (i = (0, 1) : 2) : in : a)
+  ;
+  #pragma omp task depend (iterator (i = 0 : 1 : 2 : 3) : in : a)	// { dg-error "expected '.'" }
+  ;
+  #pragma omp task depend (iterator (i = 0 : 2, 3) : in : a)	// { dg-error "expected" }
+  ;
+  #pragma omp task depend (iterator (i = N : 10 : 2, 3) : in : a)	// { dg-error "expected" }
+  ;
+  #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a)	// { dg-error "expected ':'|invalid depend kind" }
+  ;
+  #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a)	// { dg-error "invalid depend kind" }
+  ;
+  #pragma omp task depend (iterator (i = N:32) : in : b[i*2:2])
+  ;
+  #pragma omp task depend (iterator (void i = 0:1) : in : a)		// { dg-error "iterator 'i' has neither integral nor pointer type" }
+  ;
+  #pragma omp task depend (iterator (U *p = d:e:2) : in : a)
+  ;
+  #pragma omp task depend (iterator (W i = N:4, \
+				     struct U2 { W *p; } *p = 0:2) : in : a) // { dg-error "types may not be defined in iterator type" }
+  ;
+  #pragma omp task depend (iterator (i = 0:4, j = i:16) : in : a)	// { dg-error "begin expression refers to outer iterator 'i'" }
+  ;
+  #pragma omp task depend (iterator (i = N:4, j = 2:i:1) : in : a)	// { dg-error "end expression refers to outer iterator 'i'" }
+  ;
+  #pragma omp task depend (iterator (i = 0:4, j = 2:8:i) : in : a)	// { dg-error "step expression refers to outer iterator 'i'" }
+  ;
+  #pragma omp task depend (iterator (i = 1.25:2.5:3.5) : in : a)
+  ;
+  #pragma omp task depend (iterator (W *p = 23 : h) : in : a)
+  ;
+  #pragma omp task depend (iterator (const int i = N : 2) : in : a)	// { dg-error "const qualified" }
+  ;
+  #pragma omp task depend (iterator (const long long unsigned i = 0 : 2) : in : a)	// { dg-error "const qualified" }
+  ;
+}
+
+template <typename W, int N>
+void
+f2 ()
+{
+  int i, j;
+  #pragma omp for ordered(2)
+  for (i = 0; i < 64; i++)
+    for (j = 0; j < 64; j++)
+      {
+      #pragma omp ordered depend (iterator (k=0:N) : sink: i - 1, j - 1)	// { dg-error "'iterator' modifier incompatible with 'sink'" }
+      #pragma omp ordered depend (iterator (W l = 0:2:3) : source)		// { dg-error "'iterator' modifier incompatible with 'source'" }
+      }
+}
+
+template <typename U, typename V, typename W, W N, typename X, typename Y>
+void
+f3 ()
+{
+  #pragma omp task depend (iterator (U i = 0:1): in : a)		// { dg-error "iterator 'i' has neither integral nor pointer type" }
+  ;
+  #pragma omp task depend (iterator (V f = 0.2:0.4) : in : a)	// { dg-error "iterator 'f' has neither integral nor pointer type" }
+  ;
+  #pragma omp task depend (iterator (struct T *p = f:g) : in : a)	// { dg-error "invalid use of" }
+  ;
+  #pragma omp task depend (iterator (i = *d:2) : in : a)	// { dg-error "invalid cast from type 'S' to type 'int'" }
+  ;
+  #pragma omp task depend (iterator (i = 2:*d:2) : in : a)	// { dg-error "invalid cast from type 'S' to type 'int'" }
+  ;
+  #pragma omp task depend (iterator (i = 2:4:*d) : in : a)	// { dg-error "invalid cast from type 'S' to type 'int'" }
+  ;
+  #pragma omp task depend (iterator (i = 1.25:2.5:3.5) : in : a)
+  ;
+  #pragma omp task depend (iterator (W *p = 23 : h) : in : a)
+  ;
+  #pragma omp task depend (iterator (short i=1:3:N) : in : a)	// { dg-error "iterator 'i' has zero step" }
+  ;
+  #pragma omp task depend (iterator (i = 1 : 3 : N + 3 - 3) : in : a)	// { dg-error "iterator 'i' has zero step" }
+  ;
+  #pragma omp task depend (iterator (int *p = &b[6]:&b[9]:4 - 4) : in : a)	// { dg-error "iterator 'p' has zero step" }
+  ;
+  #pragma omp task depend (iterator (X i = N : 2) : in : a)	// { dg-error "const qualified" }
+  ;
+  #pragma omp task depend (iterator (Y i = 0 : 2) : in : a)	// { dg-error "const qualified" }
+  ;
+}
+
+void
+f4 ()
+{
+  f1 <struct S, float, int, 0> ();
+  f2 <int, 1> ();
+  f3 <struct S, float, int, 0, const int, const long long unsigned> ();
+}
--- libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c.jj	2018-06-12 11:41:35.817715556 +0200
+++ libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c	2018-06-12 14:39:09.759522148 +0200
@@ -0,0 +1,81 @@
+#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] + 2;
+      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] + 4;
+      return &arr[y + z];
+    case 4:
+      if (y != 0 || z > 64 || z <= 0)
+	abort ();
+      #pragma omp atomic
+      arr2[z - 1] = arr2[z - 1] + 8;
+      return &arr[z - 1];
+    default:
+      abort ();
+    }
+}
+
+volatile int beg, end, step;
+
+int
+main ()
+{
+  int m;
+  beg = 60;
+  end = -4;
+  step = -4;
+  #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) : 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;
+  }
+  for (m = 0; m < 64; m++)
+    if (arr[m] != m + 3 || arr2[m] != 15)
+      abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/depend-iterator-1.C.jj	2018-06-13 17:56:36.206038796 +0200
+++ libgomp/testsuite/libgomp.c++/depend-iterator-1.C	2018-06-13 18:07:09.183618914 +0200
@@ -0,0 +1,119 @@
+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] + 2;
+      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] + 4;
+      return &arr[y + z];
+    case 4:
+      if (y != 0 || z > 64 || z <= 0)
+	abort ();
+      #pragma omp atomic
+      arr2[z - 1] = arr2[z - 1] + 8;
+      return &arr[z - 1];
+    default:
+      abort ();
+    }
+}
+
+volatile int beg, end, step;
+
+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) : 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;
+  }
+}
+
+template <typename A, typename B, typename C>
+void
+baz (A beg, A end, A step)
+{
+  #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;
+  }
+}
+
+int
+main ()
+{
+  int m;
+  beg = 60;
+  end = -4;
+  step = -4;
+  bar<0> ();
+  for (m = 0; m < 64; m++)
+    if (arr[m] != m + 3 || arr2[m] != 15)
+      abort ();
+    else
+      arr[m] = arr2[m] = 0;
+  baz<int, long int, int *> (beg, end, step);
+  for (m = 0; m < 64; m++)
+    if (arr[m] != m + 3 || arr2[m] != 15)
+      abort ();
+  return 0;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]