--- gcc/tree-core.h.jj	2022-08-30 12:29:00.055159930 +0200
+++ gcc/tree-core.h	2022-09-01 17:05:21.271096253 +0200
@@ -345,6 +345,9 @@ enum omp_clause_code {
   /* OpenMP clause: has_device_addr (variable-list).  */
   OMP_CLAUSE_HAS_DEVICE_ADDR,
 
+  /* OpenMP clause: doacross ({source,sink}:vec).  */
+  OMP_CLAUSE_DOACROSS,
+
   /* Internal structure to hold OpenACC cache directive's variable-list.
      #pragma acc cache (variable-list).  */
   OMP_CLAUSE__CACHE_,
@@ -1525,12 +1527,18 @@ enum omp_clause_depend_kind
   OMP_CLAUSE_DEPEND_INOUT,
   OMP_CLAUSE_DEPEND_MUTEXINOUTSET,
   OMP_CLAUSE_DEPEND_INOUTSET,
-  OMP_CLAUSE_DEPEND_SOURCE,
-  OMP_CLAUSE_DEPEND_SINK,
   OMP_CLAUSE_DEPEND_DEPOBJ,
+  OMP_CLAUSE_DEPEND_INVALID,
   OMP_CLAUSE_DEPEND_LAST
 };
 
+enum omp_clause_doacross_kind
+{
+  OMP_CLAUSE_DOACROSS_SOURCE,
+  OMP_CLAUSE_DOACROSS_SINK,
+  OMP_CLAUSE_DOACROSS_LAST
+};
+
 enum omp_clause_proc_bind_kind
 {
   /* Numbers should match omp_proc_bind_t enum in omp.h.  */
@@ -1620,6 +1628,7 @@ struct GTY(()) tree_omp_clause {
     enum omp_clause_default_kind   default_kind;
     enum omp_clause_schedule_kind  schedule_kind;
     enum omp_clause_depend_kind    depend_kind;
+    enum omp_clause_doacross_kind  doacross_kind;
     /* See include/gomp-constants.h for enum gomp_map_kind's values.  */
     unsigned int		   map_kind;
     enum omp_clause_proc_bind_kind proc_bind_kind;
--- gcc/tree.h.jj	2022-08-30 12:29:00.109159197 +0200
+++ gcc/tree.h	2022-09-02 16:25:55.137047019 +0200
@@ -1722,9 +1722,16 @@ class auto_suppress_location_wrappers
 #define OMP_CLAUSE_DEPEND_KIND(NODE) \
   (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEPEND)->omp_clause.subcode.depend_kind)
 
-#define OMP_CLAUSE_DEPEND_SINK_NEGATIVE(NODE) \
+#define OMP_CLAUSE_DOACROSS_KIND(NODE) \
+  (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS)->omp_clause.subcode.doacross_kind)
+
+#define OMP_CLAUSE_DOACROSS_SINK_NEGATIVE(NODE) \
   TREE_PUBLIC (TREE_LIST_CHECK (NODE))
 
+/* True if DOACROSS clause is spelled as DEPEND.  */
+#define OMP_CLAUSE_DOACROSS_DEPEND(NODE) \
+  TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS))
+
 #define OMP_CLAUSE_MAP_KIND(NODE) \
   ((enum gomp_map_kind) OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.map_kind)
 #define OMP_CLAUSE_SET_MAP_KIND(NODE, MAP_KIND) \
@@ -1786,6 +1793,11 @@ class auto_suppress_location_wrappers
 #define OMP_CLAUSE_ORDERED_EXPR(NODE) \
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED), 0)
 
+/* True on an OMP_CLAUSE_ORDERED if stand-alone ordered construct is nested
+   inside of work-sharing loop the clause is on.  */
+#define OMP_CLAUSE_ORDERED_DOACROSS(NODE) \
+  (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED)->base.public_flag)
+
 /* True for unconstrained modifier on order(concurrent) clause.  */
 #define OMP_CLAUSE_ORDER_UNCONSTRAINED(NODE) \
   (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER)->base.public_flag)
--- gcc/tree.cc.jj	2022-08-26 09:18:25.403152829 +0200
+++ gcc/tree.cc	2022-09-01 17:06:13.675388950 +0200
@@ -294,6 +294,7 @@ unsigned const char omp_clause_num_ops[]
   2, /* OMP_CLAUSE_TO  */
   2, /* OMP_CLAUSE_MAP  */
   1, /* OMP_CLAUSE_HAS_DEVICE_ADDR  */
+  1, /* OMP_CLAUSE_DOACROSS  */
   2, /* OMP_CLAUSE__CACHE_  */
   2, /* OMP_CLAUSE_GANG  */
   1, /* OMP_CLAUSE_ASYNC  */
@@ -384,6 +385,7 @@ const char * const omp_clause_code_name[
   "to",
   "map",
   "has_device_addr",
+  "doacross",
   "_cache_",
   "gang",
   "async",
--- gcc/tree-nested.cc.jj	2022-05-27 12:48:40.468486805 +0200
+++ gcc/tree-nested.cc	2022-09-01 16:33:36.866753040 +0200
@@ -1368,6 +1368,7 @@ convert_nonlocal_omp_clauses (tree *pcla
 	case OMP_CLAUSE_IF:
 	case OMP_CLAUSE_NUM_THREADS:
 	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE_DOACROSS:
 	case OMP_CLAUSE_DEVICE:
 	case OMP_CLAUSE_NUM_TEAMS:
 	case OMP_CLAUSE_THREAD_LIMIT:
@@ -2157,6 +2158,7 @@ convert_local_omp_clauses (tree *pclause
 	case OMP_CLAUSE_IF:
 	case OMP_CLAUSE_NUM_THREADS:
 	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE_DOACROSS:
 	case OMP_CLAUSE_DEVICE:
 	case OMP_CLAUSE_NUM_TEAMS:
 	case OMP_CLAUSE_THREAD_LIMIT:
--- gcc/tree-pretty-print.cc.jj	2022-08-30 12:29:00.073159685 +0200
+++ gcc/tree-pretty-print.cc	2022-09-02 10:18:32.740423679 +0200
@@ -831,34 +831,9 @@ dump_omp_clause (pretty_printer *pp, tre
 	case OMP_CLAUSE_DEPEND_INOUTSET:
 	  name = "inoutset";
 	  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))
-	    if (TREE_CODE (t) == TREE_LIST)
-	      {
-		dump_generic_node (pp, TREE_VALUE (t), spc, flags, false);
-		if (TREE_PURPOSE (t) != integer_zero_node)
-		  {
-		    if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (t))
-		      pp_minus (pp);
-		    else
-		      pp_plus (pp);
-		    dump_generic_node (pp, TREE_PURPOSE (t), spc, flags,
-				       false);
-		  }
-		if (TREE_CHAIN (t))
-		  pp_comma (pp);
-	      }
-	    else
-	      gcc_unreachable ();
-	  pp_right_paren (pp);
-	  return;
 	default:
 	  gcc_unreachable ();
 	}
@@ -885,6 +860,49 @@ dump_omp_clause (pretty_printer *pp, tre
       }
       break;
 
+    case OMP_CLAUSE_DOACROSS:
+      pp_string (pp, OMP_CLAUSE_DOACROSS_DEPEND (clause)
+		     ? "depend(" : "doacross(");
+      switch (OMP_CLAUSE_DOACROSS_KIND (clause))
+	{
+	case OMP_CLAUSE_DOACROSS_SOURCE:
+	  if (OMP_CLAUSE_DOACROSS_DEPEND (clause))
+	    pp_string (pp, "source)");
+	  else
+	    pp_string (pp, "source:)");
+	  break;
+	case OMP_CLAUSE_DOACROSS_SINK:
+	  pp_string (pp, "sink:");
+	  if (OMP_CLAUSE_DECL (clause) == NULL_TREE)
+	    {
+	      pp_string (pp, "omp_cur_iteration-1)");
+	      break;
+	    }
+	  for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t))
+	    if (TREE_CODE (t) == TREE_LIST)
+	      {
+		dump_generic_node (pp, TREE_VALUE (t), spc, flags, false);
+		if (TREE_PURPOSE (t) != integer_zero_node)
+		  {
+		    if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (t))
+		      pp_minus (pp);
+		    else
+		      pp_plus (pp);
+		    dump_generic_node (pp, TREE_PURPOSE (t), spc, flags,
+				       false);
+		  }
+		if (TREE_CHAIN (t))
+		  pp_comma (pp);
+	      }
+	    else
+	      gcc_unreachable ();
+	  pp_right_paren (pp);
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      break;
+
     case OMP_CLAUSE_MAP:
       pp_string (pp, "map(");
       switch (OMP_CLAUSE_MAP_KIND (clause))
--- gcc/gimplify.cc.jj	2022-08-30 12:28:59.986160866 +0200
+++ gcc/gimplify.cc	2022-09-02 16:45:27.083153954 +0200
@@ -8319,9 +8319,6 @@ gimplify_omp_depend (tree *list_p, gimpl
 	  case OMP_CLAUSE_DEPEND_INOUTSET:
 	    i = 4;
 	    break;
-	  case OMP_CLAUSE_DEPEND_SOURCE:
-	  case OMP_CLAUSE_DEPEND_SINK:
-	    continue;
 	  default:
 	    gcc_unreachable ();
 	  }
@@ -8560,9 +8557,6 @@ gimplify_omp_depend (tree *list_p, gimpl
 	  case OMP_CLAUSE_DEPEND_INOUTSET:
 	    i = 4;
 	    break;
-	  case OMP_CLAUSE_DEPEND_SOURCE:
-	  case OMP_CLAUSE_DEPEND_SINK:
-	    continue;
 	  default:
 	    gcc_unreachable ();
 	  }
@@ -10406,8 +10400,8 @@ gimplify_scan_omp_clauses (tree *list_p,
 	  gimplify_omp_affinity (list_p, pre_p);
 	  remove = true;
 	  break;
-	case OMP_CLAUSE_DEPEND:
-	  if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+	case OMP_CLAUSE_DOACROSS:
+	  if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
 	    {
 	      tree deps = OMP_CLAUSE_DECL (c);
 	      while (deps && TREE_CODE (deps) == TREE_LIST)
@@ -10418,10 +10412,12 @@ gimplify_scan_omp_clauses (tree *list_p,
 				   pre_p, NULL, is_gimple_val, fb_rvalue);
 		  deps = TREE_CHAIN (deps);
 		}
-	      break;
 	    }
-	  else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
-	    break;
+	  else
+	    gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
+			== OMP_CLAUSE_DOACROSS_SOURCE);
+	  break;
+	case OMP_CLAUSE_DEPEND:
 	  if (handled_depend_iterators == -1)
 	    handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
 	  if (handled_depend_iterators)
@@ -11946,6 +11942,7 @@ gimplify_adjust_omp_clauses (gimple_seq
 	case OMP_CLAUSE_SAFELEN:
 	case OMP_CLAUSE_SIMDLEN:
 	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE_DOACROSS:
 	case OMP_CLAUSE_PRIORITY:
 	case OMP_CLAUSE_GRAINSIZE:
 	case OMP_CLAUSE_NUM_TASKS:
@@ -12429,6 +12426,29 @@ gimplify_omp_taskloop_expr (tree type, t
   OMP_FOR_CLAUSES (orig_for_stmt) = c;
 }
 
+/* Helper function of gimplify_omp_for, find OMP_ORDERED with
+   OMP_CLAUSE_DOACROSS clause inside of OMP_FOR's body.  */
+
+static tree
+find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
+{
+  switch (TREE_CODE (*tp))
+    {
+    case OMP_ORDERED:
+      if (omp_find_clause (OMP_ORDERED_CLAUSES (*tp), OMP_CLAUSE_DOACROSS))
+	return *tp;
+      break;
+    case OMP_SIMD:
+    case OMP_PARALLEL:
+    case OMP_TARGET:
+      *walk_subtrees = 0;
+      break;
+    default:
+      break;
+    }
+  return NULL_TREE;
+}
+
 /* Gimplify the gross structure of an OMP_FOR statement.  */
 
 static enum gimplify_status
@@ -12804,12 +12824,24 @@ gimplify_omp_for (tree *expr_p, gimple_s
 
   tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
   bool is_doacross = false;
-  if (c && OMP_CLAUSE_ORDERED_EXPR (c))
+  if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
+					 find_standalone_omp_ordered, NULL))
     {
+      OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
       is_doacross = true;
-      gimplify_omp_ctxp->loop_iter_var.create (TREE_VEC_LENGTH
-						 (OMP_FOR_INIT (for_stmt))
-					       * 2);
+      int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
+      gimplify_omp_ctxp->loop_iter_var.create (len * 2);
+      for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
+	if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
+	  {
+	    error_at (OMP_CLAUSE_LOCATION (*pc),
+		      "%<linear%> clause may not be specified together "
+		      "with %<ordered%> clause if stand-alone %<ordered%> "
+		      "construct is nested in it");
+	    *pc = OMP_CLAUSE_CHAIN (*pc);
+	  }
+	else
+	  pc = &OMP_CLAUSE_CHAIN (*pc);
     }
   int collapse = 1, tile = 0;
   c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
@@ -14882,21 +14914,22 @@ gimplify_omp_ordered (tree expr, gimple_
   if (gimplify_omp_ctxp)
     {
       for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
-	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-	    && gimplify_omp_ctxp->loop_iter_var.is_empty ()
-	    && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK
-		|| OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE))
+	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+	    && gimplify_omp_ctxp->loop_iter_var.is_empty ())
 	  {
 	    error_at (OMP_CLAUSE_LOCATION (c),
-		      "%<ordered%> construct with %<depend%> clause must be "
-		      "closely nested inside a loop with %<ordered%> clause "
-		      "with a parameter");
+		      "%<ordered%> construct with %qs clause must be "
+		      "closely nested inside a loop with %<ordered%> clause",
+		      OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
 	    failures++;
 	  }
-	else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-		 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+	else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+		 && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
 	  {
 	    bool fail = false;
+	    sink_c = c;
+	    if (OMP_CLAUSE_DECL (c) == NULL_TREE)
+	      continue;  /* omp_cur_iteration - 1 */
 	    for (decls = OMP_CLAUSE_DECL (c), i = 0;
 		 decls && TREE_CODE (decls) == TREE_LIST;
 		 decls = TREE_CHAIN (decls), ++i)
@@ -14919,21 +14952,24 @@ gimplify_omp_ordered (tree expr, gimple_
 	    if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
 	      {
 		error_at (OMP_CLAUSE_LOCATION (c),
-			  "number of variables in %<depend%> clause with "
+			  "number of variables in %qs clause with "
 			  "%<sink%> modifier does not match number of "
-			  "iteration variables");
+			  "iteration variables",
+			  OMP_CLAUSE_DOACROSS_DEPEND (c)
+			  ? "depend" : "doacross");
 		failures++;
 	      }
-	    sink_c = c;
 	  }
-	else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-		 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
+	else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+		 && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
 	  {
 	    if (source_c)
 	      {
 		error_at (OMP_CLAUSE_LOCATION (c),
-			  "more than one %<depend%> clause with %<source%> "
-			  "modifier on an %<ordered%> construct");
+			  "more than one %qs clause with %<source%> "
+			  "modifier on an %<ordered%> construct",
+			  OMP_CLAUSE_DOACROSS_DEPEND (source_c)
+			  ? "depend" : "doacross");
 		failures++;
 	      }
 	    else
@@ -14943,9 +14979,11 @@ gimplify_omp_ordered (tree expr, gimple_
   if (source_c && sink_c)
     {
       error_at (OMP_CLAUSE_LOCATION (source_c),
-		"%<depend%> clause with %<source%> modifier specified "
-		"together with %<depend%> clauses with %<sink%> modifier "
-		"on the same construct");
+		"%qs clause with %<source%> modifier specified "
+		"together with %qs clauses with %<sink%> modifier "
+		"on the same construct",
+		OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
+		OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
       failures++;
     }
 
--- gcc/omp-general.cc.jj	2022-08-17 16:59:09.128546118 +0200
+++ gcc/omp-general.cc	2022-09-02 17:14:13.064761612 +0200
@@ -241,8 +241,13 @@ omp_extract_for_data (gomp_for *for_stmt
 	break;
       case OMP_CLAUSE_ORDERED:
 	fd->have_ordered = true;
-	if (OMP_CLAUSE_ORDERED_EXPR (t))
-	  fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
+	if (OMP_CLAUSE_ORDERED_DOACROSS (t))
+	  {
+	    if (OMP_CLAUSE_ORDERED_EXPR (t))
+	      fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
+	    else
+	      fd->ordered = -1;
+	  }
 	break;
       case OMP_CLAUSE_SCHEDULE:
 	gcc_assert (!distribute && !taskloop);
@@ -301,6 +306,9 @@ omp_extract_for_data (gomp_for *for_stmt
 	break;
       }
 
+  if (fd->ordered == -1)
+    fd->ordered = fd->collapse;
+
   /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
      we have either the option to expensively remember at runtime how we've
      distributed work from first loop and reuse that in following loops with
--- gcc/omp-low.cc.jj	2022-08-30 12:29:00.039160147 +0200
+++ gcc/omp-low.cc	2022-09-02 18:33:16.041450721 +0200
@@ -3636,14 +3636,13 @@ check_omp_nesting_restrictions (gimple *
       break;
     case GIMPLE_OMP_TASK:
       for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
-	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-	    && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
-		|| OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
+	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
 	  {
-	    enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
+	    enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
 	    error_at (OMP_CLAUSE_LOCATION (c),
-		      "%<depend(%s)%> is only allowed in %<omp ordered%>",
-		      kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+		      "%<%s(%s)%> is only allowed in %<omp ordered%>",
+		      OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross",
+		      kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
 	    return false;
 	  }
       break;
@@ -3651,43 +3650,30 @@ check_omp_nesting_restrictions (gimple *
       for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
 	   c; c = OMP_CLAUSE_CHAIN (c))
 	{
-	  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+	  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS)
 	    {
-	      gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
-			  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
-	      continue;
-	    }
-	  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
-	  if (kind == OMP_CLAUSE_DEPEND_SOURCE
-	      || kind == OMP_CLAUSE_DEPEND_SINK)
-	    {
-	      tree oclause;
-	      /* Look for containing ordered(N) loop.  */
-	      if (ctx == NULL
-		  || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
-		  || (oclause
-			= omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
-					   OMP_CLAUSE_ORDERED)) == NULL_TREE)
-		{
-		  error_at (OMP_CLAUSE_LOCATION (c),
-			    "%<ordered%> construct with %<depend%> clause "
-			    "must be closely nested inside an %<ordered%> "
-			    "loop");
-		  return false;
-		}
-	      else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
+	      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
 		{
 		  error_at (OMP_CLAUSE_LOCATION (c),
-			    "%<ordered%> construct with %<depend%> clause "
-			    "must be closely nested inside a loop with "
-			    "%<ordered%> clause with a parameter");
+			    "invalid depend kind in omp %<ordered%> %<depend%>");
 		  return false;
 		}
+	      gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
+			  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
+	      continue;
 	    }
-	  else
+
+	  tree oclause;
+	  /* Look for containing ordered(N) loop.  */
+	  if (ctx == NULL
+	      || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
+	      || (oclause
+		  = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
+				     OMP_CLAUSE_ORDERED)) == NULL_TREE)
 	    {
 	      error_at (OMP_CLAUSE_LOCATION (c),
-			"invalid depend kind in omp %<ordered%> %<depend%>");
+			"%<ordered%> construct with %<depend%> clause "
+			"must be closely nested inside an %<ordered%> loop");
 	      return false;
 	    }
 	}
@@ -3732,14 +3718,37 @@ check_omp_nesting_restrictions (gimple *
 			  "a loop region with an %<ordered%> clause");
 		return false;
 	      }
-	    if (OMP_CLAUSE_ORDERED_EXPR (o) != NULL_TREE
-		&& omp_find_clause (c, OMP_CLAUSE_DEPEND) == NULL_TREE)
+	    if (omp_find_clause (c, OMP_CLAUSE_DOACROSS) == NULL_TREE)
 	      {
-		error_at (gimple_location (stmt),
-			  "%<ordered%> region without %<depend%> clause may "
-			  "not be closely nested inside a loop region with "
-			  "an %<ordered%> clause with a parameter");
-		return false;
+		if (OMP_CLAUSE_ORDERED_DOACROSS (o))
+		  {
+		    error_at (gimple_location (stmt),
+			      "%<ordered%> construct without %<doacross%> or "
+			      "%<depend%> clauses must not have the same "
+			      "binding region as %<ordered%> construct with "
+			      "those clauses");
+		    return false;
+		  }
+		else if (OMP_CLAUSE_ORDERED_EXPR (o))
+		  {
+		    tree co
+		      = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
+					 OMP_CLAUSE_COLLAPSE);
+		    HOST_WIDE_INT
+		      o_n = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (o));
+		    HOST_WIDE_INT c_n = 1;
+		    if (co)
+		      c_n = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (co));
+		    if (o_n != c_n)
+		      {
+			error_at (gimple_location (stmt),
+				  "%<ordered%> construct without %<doacross%> "
+				  "or %<depend%> clauses binds to loop where "
+				  "%<collapse%> argument %wd is different from "
+				  "%<ordered%> argument %wd", c_n, o_n);
+			return false;
+		      }
+		  }
 	      }
 	    return true;
 	  case GIMPLE_OMP_TARGET:
@@ -3793,14 +3802,12 @@ check_omp_nesting_restrictions (gimple *
       break;
     case GIMPLE_OMP_TARGET:
       for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
-	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-	    && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
-		|| OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
+	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
 	  {
-	    enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
+	    enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
 	    error_at (OMP_CLAUSE_LOCATION (c),
 		      "%<depend(%s)%> is only allowed in %<omp ordered%>",
-		      kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+		      kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
 	    return false;
 	  }
       if (is_gimple_omp_offloaded (stmt)
@@ -9743,8 +9750,8 @@ lower_omp_ordered_clauses (gimple_stmt_i
 
   tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
   tree c = gimple_omp_ordered_clauses (ord_stmt);
-  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-      && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+      && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
     {
       /* Merge depend clauses from multiple adjacent
 	 #pragma omp ordered depend(sink:...) constructs
@@ -9766,8 +9773,8 @@ lower_omp_ordered_clauses (gimple_stmt_i
 	  gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
 	  c = gimple_omp_ordered_clauses (ord_stmt2);
 	  if (c == NULL_TREE
-	      || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
-	      || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
+	      || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS
+	      || OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
 	    break;
 	  while (*list_p)
 	    list_p = &OMP_CLAUSE_CHAIN (*list_p);
@@ -9834,8 +9841,8 @@ lower_omp_ordered_clauses (gimple_stmt_i
     {
       bool remove = false;
 
-      gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
-      if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
+      gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS);
+      if (OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
 	goto next_ordered_clause;
 
       tree vec;
@@ -9986,7 +9993,7 @@ lower_omp_ordered (gimple_stmt_iterator
 				  OMP_CLAUSE_THREADS);
 
   if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
-		       OMP_CLAUSE_DEPEND))
+		       OMP_CLAUSE_DOACROSS))
     {
       /* FIXME: This is needs to be moved to the expansion to verify various
 	 conditions only testable on cfg with dominators computed, and also
@@ -12362,9 +12369,6 @@ lower_depend_clauses (tree *pclauses, gi
 	case OMP_CLAUSE_DEPEND_INOUTSET:
 	  cnt[4]++;
 	  break;
-	case OMP_CLAUSE_DEPEND_SOURCE:
-	case OMP_CLAUSE_DEPEND_SINK:
-	  /* FALLTHRU */
 	default:
 	  gcc_unreachable ();
 	}
--- gcc/omp-expand.cc.jj	2022-08-30 12:29:00.016160459 +0200
+++ gcc/omp-expand.cc	2022-09-02 18:18:37.253370510 +0200
@@ -3298,6 +3298,11 @@ expand_omp_ordered_sink (gimple_stmt_ite
   gimple_stmt_iterator gsi2 = *gsi;
   bool warned_step = false;
 
+  if (deps == NULL)
+    {
+      sorry_at (loc, "%<doacross(sink:omp_cur_iteration-1)%> not supported yet");
+      return;
+    }
   for (i = 0; i < fd->ordered; i++)
     {
       tree step = NULL_TREE;
@@ -3321,9 +3326,11 @@ expand_omp_ordered_sink (gimple_stmt_ite
 		break;
 	      forward = tree_int_cst_sgn (step) != -1;
 	    }
-	  if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
-	    warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier "
-				"waiting for lexically later iteration");
+	  if (forward ^ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
+	    warning_at (loc, 0, "%qs clause with %<sink%> modifier "
+				"waiting for lexically later iteration",
+			OMP_CLAUSE_DOACROSS_DEPEND (c)
+			? "depend" : "doacross");
 	  break;
 	}
       deps = TREE_CHAIN (deps);
@@ -3377,13 +3384,13 @@ expand_omp_ordered_sink (gimple_stmt_ite
 	  tree co = fold_convert_loc (loc, itype, off);
 	  if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
 	    {
-	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+	      if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
 		co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
 	      a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
 				   TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
 				   co);
 	    }
-	  else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+	  else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
 	    a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
 				 fd->loops[i].v, co);
 	  else
@@ -3392,13 +3399,13 @@ expand_omp_ordered_sink (gimple_stmt_ite
 	  if (step)
 	    {
 	      tree t1, t2;
-	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+	      if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
 		t1 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
 				      fd->loops[i].n1);
 	      else
 		t1 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
 				      fd->loops[i].n2);
-	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+	      if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
 		t2 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
 				      fd->loops[i].n2);
 	      else
@@ -3420,14 +3427,14 @@ expand_omp_ordered_sink (gimple_stmt_ite
 	    }
 	  else if (fd->loops[i].cond_code == LT_EXPR)
 	    {
-	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+	      if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
 		t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
 				     fd->loops[i].n1);
 	      else
 		t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
 				     fd->loops[i].n2);
 	    }
-	  else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+	  else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
 	    t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
 				 fd->loops[i].n2);
 	  else
@@ -3459,9 +3466,11 @@ expand_omp_ordered_sink (gimple_stmt_ite
 			       build_int_cst (itype, 0));
 	  if (integer_zerop (t) && !warned_step)
 	    {
-	      warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier "
+	      warning_at (loc, 0, "%qs clause with %<sink%> modifier "
 				  "refers to iteration never in the iteration "
-				  "space");
+				  "space",
+			  OMP_CLAUSE_DOACROSS_DEPEND (c)
+			  ? "depend" : "doacross");
 	      warned_step = true;
 	    }
 	  cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
@@ -3486,7 +3495,7 @@ expand_omp_ordered_sink (gimple_stmt_ite
 						s));
       else
 	off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
-      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+      if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
 	off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
       off = fold_convert_loc (loc, fd->iter_type, off);
       if (i <= fd->collapse - 1 && fd->collapse > 1)
@@ -3559,13 +3568,13 @@ expand_omp_ordered_source_sink (struct o
 	tree c;
 	for (c = gimple_omp_ordered_clauses (ord_stmt);
 	     c; c = OMP_CLAUSE_CHAIN (c))
-	  if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
+	  if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
 	    break;
 	if (c)
 	  expand_omp_ordered_source (&gsi, fd, counts, loc);
 	for (c = gimple_omp_ordered_clauses (ord_stmt);
 	     c; c = OMP_CLAUSE_CHAIN (c))
-	  if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+	  if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
 	    expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
 	gsi_remove (&gsi, true);
       }
@@ -10479,7 +10488,7 @@ expand_omp (struct omp_region *region)
 	    gomp_ordered *ord_stmt
 	      = as_a <gomp_ordered *> (last_stmt (region->entry));
 	    if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
-				 OMP_CLAUSE_DEPEND))
+				 OMP_CLAUSE_DOACROSS))
 	      {
 		/* We'll expand these when expanding corresponding
 		   worksharing region with ordered(n) clause.  */
@@ -10609,7 +10618,7 @@ build_omp_regions_1 (basic_block bb, str
 	  else if (code == GIMPLE_OMP_ORDERED
 		   && omp_find_clause (gimple_omp_ordered_clauses
 					 (as_a <gomp_ordered *> (stmt)),
-				       OMP_CLAUSE_DEPEND))
+				       OMP_CLAUSE_DOACROSS))
 	    /* #pragma omp ordered depend is also just a stand-alone
 	       directive.  */
 	    region = NULL;
@@ -10835,7 +10844,7 @@ omp_make_gimple_edges (basic_block bb, s
       fallthru = true;
       if (omp_find_clause (gimple_omp_ordered_clauses
 			     (as_a <gomp_ordered *> (last)),
-			   OMP_CLAUSE_DEPEND))
+			   OMP_CLAUSE_DOACROSS))
 	cur_region = cur_region->outer;
       break;
 
--- gcc/lto-streamer-out.cc.jj	2022-01-18 11:58:59.686980571 +0100
+++ gcc/lto-streamer-out.cc	2022-09-01 16:35:03.823584108 +0200
@@ -1553,6 +1553,9 @@ hash_tree (struct streamer_tree_cache_d
 	case OMP_CLAUSE_DEPEND:
 	  val = OMP_CLAUSE_DEPEND_KIND (t);
 	  break;
+	case OMP_CLAUSE_DOACROSS:
+	  val = OMP_CLAUSE_DOACROSS_KIND (t);
+	  break;
 	case OMP_CLAUSE_MAP:
 	  val = OMP_CLAUSE_MAP_KIND (t);
 	  break;
--- gcc/tree-streamer-in.cc.jj	2022-05-09 09:09:20.817466314 +0200
+++ gcc/tree-streamer-in.cc	2022-09-01 16:32:09.156932116 +0200
@@ -453,6 +453,11 @@ unpack_ts_omp_clause_value_fields (class
       OMP_CLAUSE_DEPEND_KIND (expr)
 	= bp_unpack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST);
       break;
+    case OMP_CLAUSE_DOACROSS:
+      OMP_CLAUSE_DOACROSS_KIND (expr)
+	= bp_unpack_enum (bp, omp_clause_doacross_kind,
+			  OMP_CLAUSE_DOACROSS_LAST);
+      break;
     case OMP_CLAUSE_MAP:
       OMP_CLAUSE_SET_MAP_KIND (expr, bp_unpack_enum (bp, gomp_map_kind,
 						     GOMP_MAP_LAST));
--- gcc/tree-streamer-out.cc.jj	2022-02-04 14:36:56.342586625 +0100
+++ gcc/tree-streamer-out.cc	2022-09-01 16:32:38.916532065 +0200
@@ -419,6 +419,10 @@ pack_ts_omp_clause_value_fields (struct
       bp_pack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST,
 		    OMP_CLAUSE_DEPEND_KIND (expr));
       break;
+    case OMP_CLAUSE_DOACROSS:
+      bp_pack_enum (bp, omp_clause_doacross_kind, OMP_CLAUSE_DOACROSS_LAST,
+		    OMP_CLAUSE_DOACROSS_KIND (expr));
+      break;
     case OMP_CLAUSE_MAP:
       bp_pack_enum (bp, gomp_map_kind, GOMP_MAP_LAST,
 		    OMP_CLAUSE_MAP_KIND (expr));
--- gcc/c-family/c-pragma.h.jj	2022-08-30 12:28:59.909161910 +0200
+++ gcc/c-family/c-pragma.h	2022-09-01 14:34:17.356367234 +0200
@@ -108,6 +108,7 @@ enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_DEVICE,
   PRAGMA_OMP_CLAUSE_DEVICE_TYPE,
   PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
+  PRAGMA_OMP_CLAUSE_DOACROSS,
   PRAGMA_OMP_CLAUSE_ENTER,
   PRAGMA_OMP_CLAUSE_FILTER,
   PRAGMA_OMP_CLAUSE_FINAL,
--- gcc/c-family/c-omp.cc.jj	2022-08-30 12:28:59.874162385 +0200
+++ gcc/c-family/c-omp.cc	2022-09-01 17:39:13.733664070 +0200
@@ -714,8 +714,17 @@ c_finish_omp_depobj (location_t loc, tre
 
   if (clause)
     {
-      gcc_assert (TREE_CODE (clause) == OMP_CLAUSE
-		  && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
+      gcc_assert (TREE_CODE (clause) == OMP_CLAUSE);
+      if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS)
+	{
+	  error_at (OMP_CLAUSE_LOCATION (clause),
+		    "%<depend(%s)%> is only allowed in %<omp ordered%>",
+		    OMP_CLAUSE_DOACROSS_KIND (clause)
+		    == OMP_CLAUSE_DOACROSS_SOURCE
+		    ? "source" : "sink");
+	  return;
+	}
+      gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
       if (OMP_CLAUSE_CHAIN (clause))
 	error_at (OMP_CLAUSE_LOCATION (clause),
 		  "more than one locator in %<depend%> clause on %<depobj%> "
@@ -727,13 +736,6 @@ c_finish_omp_depobj (location_t loc, tre
 		    "%<depobj%> dependence type specified in %<depend%> "
 		    "clause on %<depobj%> construct");
 	  return;
-	case OMP_CLAUSE_DEPEND_SOURCE:
-	case OMP_CLAUSE_DEPEND_SINK:
-	  error_at (OMP_CLAUSE_LOCATION (clause),
-		    "%<depend(%s)%> is only allowed in %<omp ordered%>",
-		    OMP_CLAUSE_DEPEND_KIND (clause) == OMP_CLAUSE_DEPEND_SOURCE
-		    ? "source" : "sink");
-	  return;
 	case OMP_CLAUSE_DEPEND_IN:
 	case OMP_CLAUSE_DEPEND_OUT:
 	case OMP_CLAUSE_DEPEND_INOUT:
@@ -764,8 +766,8 @@ c_finish_omp_depobj (location_t loc, tre
 	  gcc_unreachable ();
 	}
     }
   else
-    gcc_assert (kind != OMP_CLAUSE_DEPEND_SOURCE);
+    gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID);
 
   if (depobj == error_mark_node)
     return;
--- gcc/c/c-parser.cc.jj	2022-09-01 09:37:58.008630749 +0200
+++ gcc/c/c-parser.cc	2022-09-02 15:52:03.948221268 +0200
@@ -12814,6 +12814,8 @@ c_parser_omp_clause_name (c_parser *pars
 	    result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
 	  else if (!strcmp ("dist_schedule", p))
 	    result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+	  else if (!strcmp ("doacross", p))
+	    result = PRAGMA_OMP_CLAUSE_DOACROSS;
 	  break;
 	case 'e':
 	  if (!strcmp ("enter", p))
@@ -15962,8 +15964,8 @@ c_parser_omp_clause_simdlen (c_parser *p
 */
 
 static tree
-c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
-				 tree list)
+c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
+				   tree list, bool depend_p)
 {
   tree vec = NULL;
   if (c_parser_next_token_is_not (parser, CPP_NAME)
@@ -15973,6 +15975,31 @@ c_parser_omp_clause_depend_sink (c_parse
       return list;
     }
 
+  if (!depend_p)
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "omp_cur_iteration") == 0
+	  && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
+	  && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER
+	  && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN)
+	{
+	  tree val = c_parser_peek_nth_token (parser, 3)->value;
+	  if (integer_onep (val)
+	      && comptypes (TREE_TYPE (val), integer_type_node))
+	    {
+	      c_parser_consume_token (parser);
+	      c_parser_consume_token (parser);
+	      c_parser_consume_token (parser);
+	      tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+	      OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+	      OMP_CLAUSE_CHAIN (u) = list;
+	      return u;
+	    }
+	}
+    }
+
+
+
   while (c_parser_next_token_is (parser, CPP_NAME)
 	 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
     {
@@ -16018,7 +16045,7 @@ c_parser_omp_clause_depend_sink (c_parse
 	{
 	  vec = tree_cons (addend, t, vec);
 	  if (neg)
-	    OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+	    OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
 	}
 
       if (c_parser_next_token_is_not (parser, CPP_COMMA)
@@ -16032,8 +16059,9 @@ c_parser_omp_clause_depend_sink (c_parse
   if (vec == NULL_TREE)
     return list;
 
-  tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
-  OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK;
+  tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+  OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+  OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
   OMP_CLAUSE_DECL (u) = nreverse (vec);
   OMP_CLAUSE_CHAIN (u) = list;
   return u;
@@ -16225,6 +16253,7 @@ 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_LAST;
+  enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
   tree nl, c, iterators = NULL_TREE;
 
   matching_parens parens;
@@ -16256,9 +16285,9 @@ c_parser_omp_clause_depend (c_parser *pa
       else if (strcmp ("depobj", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_DEPOBJ;
       else if (strcmp ("sink", p) == 0)
-	kind = OMP_CLAUSE_DEPEND_SINK;
+	dkind = OMP_CLAUSE_DOACROSS_SINK;
       else if (strcmp ("source", p) == 0)
-	kind = OMP_CLAUSE_DEPEND_SOURCE;
+	dkind = OMP_CLAUSE_DOACROSS_SOURCE;
       else
 	goto invalid_kind;
       break;
@@ -16268,18 +16297,20 @@ c_parser_omp_clause_depend (c_parser *pa
   c_parser_consume_token (parser);
 
   if (iterators
-      && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+      && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
+	  || dkind == OMP_CLAUSE_DOACROSS_SINK))
     {
       pop_scope ();
       error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
-		kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+		dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
       iterators = NULL_TREE;
     }
 
-  if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+  if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
     {
-      c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
-      OMP_CLAUSE_DEPEND_KIND (c) = kind;
+      c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+      OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
+      OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
       OMP_CLAUSE_DECL (c) = NULL_TREE;
       OMP_CLAUSE_CHAIN (c) = list;
       parens.skip_until_found_close (parser);
@@ -16289,8 +16320,8 @@ c_parser_omp_clause_depend (c_parser *pa
   if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     goto resync_fail;
 
-  if (kind == OMP_CLAUSE_DEPEND_SINK)
-    nl = c_parser_omp_clause_depend_sink (parser, clause_loc, list);
+  if (dkind == OMP_CLAUSE_DOACROSS_SINK)
+    nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true);
   else
     {
       nl = c_parser_omp_variable_list (parser, clause_loc,
@@ -16326,6 +16357,65 @@ c_parser_omp_clause_depend (c_parser *pa
   return list;
 }
 
+/* OpenMP 5.2:
+   doacross ( source : )
+   doacross ( source : omp_cur_iteration )
+
+   doacross ( sink : vec )
+   doacross ( sink : omp_cur_iteration - logical_iteration )  */
+
+static tree
+c_parser_omp_clause_doacross (c_parser *parser, tree list)
+{
+  location_t clause_loc = c_parser_peek_token (parser)->location;
+  enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
+  tree nl;
+  const char *p;
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return list;
+
+  if (c_parser_next_token_is_not (parser, CPP_NAME))
+    goto invalid_kind;
+
+  p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  if (strcmp ("sink", p) == 0)
+    kind = OMP_CLAUSE_DOACROSS_SINK;
+  else if (strcmp ("source", p) == 0)
+    kind = OMP_CLAUSE_DOACROSS_SOURCE;
+  else
+    goto invalid_kind;
+
+  c_parser_consume_token (parser);
+
+  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+    goto resync_fail;
+
+  if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
+    {
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+		     "omp_cur_iteration") == 0)
+	c_parser_consume_token (parser);
+      nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+      OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
+      OMP_CLAUSE_DECL (nl) = NULL_TREE;
+      OMP_CLAUSE_CHAIN (nl) = list;
+    }
+  else
+    nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false);
+
+  parens.skip_until_found_close (parser);
+  return nl;
+
+ invalid_kind:
+  c_parser_error (parser, "invalid doacross kind");
+ resync_fail:
+  parens.skip_until_found_close (parser);
+  return list;
+}
+
 /* OpenMP 4.0:
    map ( map-kind: variable-list )
    map ( variable-list )
@@ -17243,6 +17333,10 @@ c_parser_omp_all_clauses (c_parser *pars
 	  clauses = c_parser_omp_clause_depend (parser, clauses);
 	  c_name = "depend";
 	  break;
+	case PRAGMA_OMP_CLAUSE_DOACROSS:
+	  clauses = c_parser_omp_clause_doacross (parser, clauses);
+	  c_name = "doacross";
+	  break;
 	case PRAGMA_OMP_CLAUSE_MAP:
 	  clauses = c_parser_omp_clause_map (parser, clauses);
 	  c_name = "map";
@@ -19187,7 +19281,7 @@ c_parser_omp_depobj (c_parser *parser)
 
   parens.skip_until_found_close (parser);
   tree clause = NULL_TREE;
-  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
   location_t c_loc = c_parser_peek_token (parser)->location;
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
@@ -19226,7 +19320,7 @@ c_parser_omp_depobj (c_parser *parser)
 		  else if (!strcmp ("inoutset", p2))
 		    kind = OMP_CLAUSE_DEPEND_INOUTSET;
 		}
-	      if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+	      if (kind == OMP_CLAUSE_DEPEND_INVALID)
 		{
 		  clause = error_mark_node;
 		  error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
@@ -19238,7 +19332,7 @@ c_parser_omp_depobj (c_parser *parser)
 	    clause = error_mark_node;
 	}
     }
-  if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
+  if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
     {
       clause = error_mark_node;
       error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
@@ -19437,19 +19531,6 @@ c_parser_omp_for_loop (location_t loc, c
 	= build_int_cst (NULL_TREE, collapse);
       ordered = collapse;
     }
-  if (ordered)
-    {
-      for (tree *pc = &clauses; *pc; )
-	if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
-	  {
-	    error_at (OMP_CLAUSE_LOCATION (*pc),
-		      "%<linear%> clause may not be specified together "
-		      "with %<ordered%> clause with a parameter");
-	    *pc = OMP_CLAUSE_CHAIN (*pc);
-	  }
-	else
-	  pc = &OMP_CLAUSE_CHAIN (*pc);
-    }
 
   gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
   count = ordered ? ordered : collapse;
@@ -19887,15 +19968,6 @@ c_parser_omp_simd (location_t loc, c_par
     {
       omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
       clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
-      tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
-				OMP_CLAUSE_ORDERED);
-      if (c && OMP_CLAUSE_ORDERED_EXPR (c))
-	{
-	  error_at (OMP_CLAUSE_LOCATION (c),
-		    "%<ordered%> clause with parameter may not be specified "
-		    "on %qs construct", p_name);
-	  OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE;
-	}
     }
 
   block = c_begin_compound_stmt (true);
@@ -20134,14 +20206,18 @@ c_parser_omp_masked (location_t loc, c_p
    # pragma omp ordered ordered-clauses new-line
      structured-block
 
-   # pragma omp ordered depend-clauses new-line  */
+   # pragma omp ordered depend-clauses new-line
+
+   OpenMP 5.2
+   # pragma omp ordered doacross-clauses new-line  */
 
 #define OMP_ORDERED_CLAUSE_MASK					\
 	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS)	\
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
 
 #define OMP_ORDERED_DEPEND_CLAUSE_MASK				\
-	(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
+	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)	\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
 
 static bool
 c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
@@ -20161,7 +20237,7 @@ c_parser_omp_ordered (c_parser *parser,
     {
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
 
-      if (!strcmp ("depend", p))
+      if (!strcmp ("depend", p) || !strcmp ("doacross", p))
 	{
 	  if (!flag_openmp)	/* flag_openmp_simd  */
 	    {
@@ -20171,8 +20247,8 @@ c_parser_omp_ordered (c_parser *parser,
 	  if (context == pragma_stmt)
 	    {
 	      error_at (loc,
-			"%<#pragma omp ordered%> with %<depend%> clause may "
-			"only be used in compound statements");
+			"%<#pragma omp ordered%> with %qs clause may "
+			"only be used in compound statements", p);
 	      c_parser_skip_to_pragma_eol (parser, false);
 	      return true;
 	    }
--- gcc/c/c-typeck.cc.jj	2022-09-01 09:37:58.014630667 +0200
+++ gcc/c/c-typeck.cc	2022-09-02 10:17:07.680560840 +0200
@@ -14834,15 +14834,11 @@ c_finish_omp_clauses (tree clauses, enum
 	    }
 	  break;
 
-	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE_DOACROSS:
 	  t = OMP_CLAUSE_DECL (c);
 	  if (t == NULL_TREE)
-	    {
-	      gcc_assert (OMP_CLAUSE_DEPEND_KIND (c)
-			  == OMP_CLAUSE_DEPEND_SOURCE);
-	      break;
-	    }
-	  if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+	    break;
+	  if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
 	    {
 	      gcc_assert (TREE_CODE (t) == TREE_LIST);
 	      for (; t; t = TREE_CHAIN (t))
@@ -14870,7 +14866,8 @@ c_finish_omp_clauses (tree clauses, enum
 		}
 	      break;
 	    }
-	  /* FALLTHRU */
+	  gcc_unreachable ();
+	case OMP_CLAUSE_DEPEND:
 	case OMP_CLAUSE_AFFINITY:
 	  t = OMP_CLAUSE_DECL (c);
 	  if (TREE_CODE (t) == TREE_LIST
--- gcc/cp/parser.cc.jj	2022-08-26 09:18:25.255154767 +0200
+++ gcc/cp/parser.cc	2022-09-02 15:51:28.675690445 +0200
@@ -11979,14 +11979,18 @@ cp_parser_handle_statement_omp_attribute
 	    if (dir->id == PRAGMA_OMP_ORDERED)
 	      {
 		/* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
-		   depend clause.  */
-		if (directive[1] && strcmp (directive[1], "depend") == 0)
+		   depend/doacross clause.  */
+		if (directive[1]
+		    && (strcmp (directive[1], "depend") == 0
+			|| strcmp (directive[1], "doacross") == 0))
 		  kind = C_OMP_DIR_STANDALONE;
 		else if (first + 2 < last
 			 && first[1].type == CPP_COMMA
 			 && first[2].type == CPP_NAME
-			 && strcmp (IDENTIFIER_POINTER (first[2].u.value),
-				    "depend") == 0)
+			 && (strcmp (IDENTIFIER_POINTER (first[2].u.value),
+				     "depend") == 0
+			     || strcmp (IDENTIFIER_POINTER (first[2].u.value),
+					"doacross") == 0))
 		  kind = C_OMP_DIR_STANDALONE;
 	      }
 	    else if (dir->id == PRAGMA_OMP_ERROR)
@@ -36587,6 +36591,8 @@ cp_parser_omp_clause_name (cp_parser *pa
 	    result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
 	  else if (!strcmp ("dist_schedule", p))
 	    result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+	  else if (!strcmp ("doacross", p))
+	    result = PRAGMA_OMP_CLAUSE_DOACROSS;
 	  break;
 	case 'e':
 	  if (!strcmp ("enter", p))
@@ -39314,8 +39320,8 @@ cp_parser_omp_clause_simdlen (cp_parser
 */
 
 static tree
-cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc,
-				  tree list)
+cp_parser_omp_clause_doacross_sink (cp_parser *parser, location_t clause_loc,
+				    tree list, bool depend_p)
 {
   tree vec = NULL;
 
@@ -39325,6 +39331,29 @@ cp_parser_omp_clause_depend_sink (cp_par
       return list;
     }
 
+  if (!depend_p)
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      if (strcmp (IDENTIFIER_POINTER (id), "omp_cur_iteration") == 0
+	  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_MINUS)
+	  && cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
+	  && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN))
+	{
+	  tree val = cp_lexer_peek_nth_token (parser->lexer, 3)->u.value;
+	  if (integer_onep (val)
+	      && same_type_p (TREE_TYPE (val), integer_type_node))
+	    {
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_lexer_consume_token (parser->lexer);
+	      tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+	      OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+	      OMP_CLAUSE_CHAIN (u) = list;
+	      return u;
+	    }
+	}
+    }
+
   while (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
       location_t id_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -39372,7 +39401,7 @@ cp_parser_omp_clause_depend_sink (cp_par
 	{
 	  vec = tree_cons (addend, t, vec);
 	  if (neg)
-	    OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+	    OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
 	}
 
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
@@ -39384,8 +39413,9 @@ cp_parser_omp_clause_depend_sink (cp_par
 
   if (vec)
     {
-      tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
-      OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK;
+      tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+      OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+      OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
       OMP_CLAUSE_DECL (u) = nreverse (vec);
       OMP_CLAUSE_CHAIN (u) = list;
       return u;
@@ -39634,6 +39664,7 @@ cp_parser_omp_clause_depend (cp_parser *
 {
   tree nlist, c, iterators = NULL_TREE;
   enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
+  enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
 
   matching_parens parens;
   if (!parens.require_open (parser))
@@ -39667,9 +39698,9 @@ cp_parser_omp_clause_depend (cp_parser *
       else if (strcmp ("depobj", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_DEPOBJ;
       else if (strcmp ("sink", p) == 0)
-	kind = OMP_CLAUSE_DEPEND_SINK;
+	dkind = OMP_CLAUSE_DOACROSS_SINK;
       else if (strcmp ("source", p) == 0)
-	kind = OMP_CLAUSE_DEPEND_SOURCE;
+	dkind = OMP_CLAUSE_DOACROSS_SOURCE;
       else
 	goto invalid_kind;
       break;
@@ -39679,18 +39710,20 @@ cp_parser_omp_clause_depend (cp_parser *
   cp_lexer_consume_token (parser->lexer);
 
   if (iterators
-      && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+      && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
+	  || dkind == OMP_CLAUSE_DOACROSS_SINK))
     {
       poplevel (0, 1, 0);
       error_at (loc, "%<iterator%> modifier incompatible with %qs",
-		kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+		dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
       iterators = NULL_TREE;
     }
 
-  if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+  if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
     {
-      c = build_omp_clause (loc, OMP_CLAUSE_DEPEND);
-      OMP_CLAUSE_DEPEND_KIND (c) = kind;
+      c = build_omp_clause (loc, OMP_CLAUSE_DOACROSS);
+      OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
+      OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
       OMP_CLAUSE_DECL (c) = NULL_TREE;
       OMP_CLAUSE_CHAIN (c) = list;
       if (!parens.require_close (parser))
@@ -39703,9 +39736,9 @@ cp_parser_omp_clause_depend (cp_parser *
   if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
     goto resync_fail;
 
-  if (kind == OMP_CLAUSE_DEPEND_SINK)
+  if (dkind == OMP_CLAUSE_DOACROSS_SINK)
     {
-      nlist = cp_parser_omp_clause_depend_sink (parser, loc, list);
+      nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, true);
       if (!parens.require_close (parser))
 	cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
 					       /*or_comma=*/false,
@@ -39746,6 +39779,73 @@ cp_parser_omp_clause_depend (cp_parser *
   return list;
 }
 
+/* OpenMP 5.2:
+   doacross ( source : )
+   doacross ( source : omp_cur_iteration )
+
+   doacross ( sink : vec )
+   doacross ( sink : omp_cur_iteration - logical_iteration )  */
+
+static tree
+cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc)
+{
+  tree nlist;
+  enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return list;
+
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+    {
+    invalid_kind:
+      cp_parser_error (parser, "invalid doacross kind");
+    resync_fail:
+      cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+					     /*or_comma=*/false,
+					     /*consume_paren=*/true);
+      return list;
+    }
+
+  tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+  const char *p = IDENTIFIER_POINTER (id);
+
+  if (strcmp ("sink", p) == 0)
+    kind = OMP_CLAUSE_DOACROSS_SINK;
+  else if (strcmp ("source", p) == 0)
+    kind = OMP_CLAUSE_DOACROSS_SOURCE;
+  else
+    goto invalid_kind;
+
+  cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+    goto resync_fail;
+
+  if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
+    {
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+	{
+	  id = cp_lexer_peek_token (parser->lexer)->u.value;
+	  p = IDENTIFIER_POINTER (id);
+	  if (strcmp (p, "omp_cur_iteration") == 0)
+	    cp_lexer_consume_token (parser->lexer);
+	}
+      nlist = build_omp_clause (loc, OMP_CLAUSE_DOACROSS);
+      OMP_CLAUSE_DOACROSS_KIND (nlist) = OMP_CLAUSE_DOACROSS_SOURCE;
+      OMP_CLAUSE_DECL (nlist) = NULL_TREE;
+      OMP_CLAUSE_CHAIN (nlist) = list;
+    }
+  else
+    nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, false);
+
+  if (!parens.require_close (parser))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+					   /*or_comma=*/false,
+					   /*consume_paren=*/true);
+  return nlist;
+}
+
 /* OpenMP 4.0:
    map ( map-kind : variable-list )
    map ( variable-list )
@@ -40688,6 +40788,11 @@ cp_parser_omp_all_clauses (cp_parser *pa
 						 token->location);
 	  c_name = "depend";
 	  break;
+	case PRAGMA_OMP_CLAUSE_DOACROSS:
+	  clauses = cp_parser_omp_clause_doacross (parser, clauses,
+						   token->location);
+	  c_name = "doacross";
+	  break;
 	case PRAGMA_OMP_CLAUSE_DETACH:
 	  clauses = cp_parser_omp_clause_detach (parser, clauses);
 	  c_name = "detach";
@@ -41926,7 +42031,7 @@ cp_parser_omp_depobj (cp_parser *parser,
 					   /*consume_paren=*/true);
 
   tree clause = NULL_TREE;
-  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
   location_t c_loc = cp_lexer_peek_token (parser->lexer)->location;
   /* For now only in C++ attributes, do it always for OpenMP 5.1.  */
   if (parser->lexer->in_omp_attribute_pragma
@@ -41974,7 +42079,7 @@ cp_parser_omp_depobj (cp_parser *parser,
 		  else if (!strcmp ("inoutset", p2))
 		    kind = OMP_CLAUSE_DEPEND_INOUTSET;
 		}
-	      if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+	      if (kind == OMP_CLAUSE_DEPEND_INVALID)
 		{
 		  clause = error_mark_node;
 		  error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
@@ -41990,7 +42095,7 @@ cp_parser_omp_depobj (cp_parser *parser,
 	    clause = error_mark_node;
 	}
     }
-  if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
+  if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
     {
       clause = error_mark_node;
       error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
@@ -42822,19 +42927,6 @@ cp_parser_omp_for_loop (cp_parser *parse
 	= build_int_cst (NULL_TREE, collapse);
       ordered = collapse;
     }
-  if (ordered)
-    {
-      for (tree *pc = &clauses; *pc; )
-	if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
-	  {
-	    error_at (OMP_CLAUSE_LOCATION (*pc),
-		      "%<linear%> clause may not be specified together "
-		      "with %<ordered%> clause with a parameter");
-	    *pc = OMP_CLAUSE_CHAIN (*pc);
-	  }
-	else
-	  pc = &OMP_CLAUSE_CHAIN (*pc);
-    }
 
   gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
   count = ordered ? ordered : collapse;
@@ -43286,15 +43378,6 @@ cp_parser_omp_simd (cp_parser *parser, c
     {
       cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
       clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
-      tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
-				OMP_CLAUSE_ORDERED);
-      if (c && OMP_CLAUSE_ORDERED_EXPR (c))
-	{
-	  error_at (OMP_CLAUSE_LOCATION (c),
-		    "%<ordered%> clause with parameter may not be specified "
-		    "on %qs construct", p_name);
-	  OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE;
-	}
     }
 
   keep_next_level (true);
@@ -43556,7 +43639,8 @@ cp_parser_omp_masked (cp_parser *parser,
 	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
 
 #define OMP_ORDERED_DEPEND_CLAUSE_MASK				\
-	(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
+	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)	\
+	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
 
 static bool
 cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok,
@@ -43575,7 +43659,7 @@ cp_parser_omp_ordered (cp_parser *parser
       tree id = cp_lexer_peek_nth_token (parser->lexer, n)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
 
-      if (strcmp (p, "depend") == 0)
+      if (strcmp (p, "depend") == 0 || strcmp (p, "doacross") == 0)
 	{
 	  if (!flag_openmp)	/* flag_openmp_simd */
 	    {
@@ -43585,8 +43669,8 @@ cp_parser_omp_ordered (cp_parser *parser
 	  if (context == pragma_stmt)
 	    {
 	      error_at (pragma_tok->location, "%<#pragma omp ordered%> with "
-			"%<depend%> clause may only be used in compound "
-			"statements");
+			"%qs clause may only be used in compound "
+			"statements", p);
 	      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
 	      return true;
 	    }
--- gcc/cp/pt.cc.jj	2022-08-18 09:05:49.937120132 +0200
+++ gcc/cp/pt.cc	2022-09-01 18:35:47.558830758 +0200
@@ -17830,8 +17830,8 @@ tsubst_omp_clause_decl (tree decl, tree
     }
 
   /* 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
+     OMP_CLAUSE_DOACROSS_KIND).  An OMP_CLAUSE_DOACROSS (with a depend
+     kind of OMP_CLAUSE_DOACROSS_SINK) can also be represented as a
      TREE_LIST.  We can handle it exactly the same as an array section
      (purpose, value, and a chain), even though the nomenclature
      (low_bound, length, etc) is different.  */
@@ -17849,8 +17849,8 @@ tsubst_omp_clause_decl (tree decl, tree
 	  && TREE_CHAIN (decl) == chain)
 	return decl;
       tree ret = tree_cons (low_bound, length, chain);
-      OMP_CLAUSE_DEPEND_SINK_NEGATIVE (ret)
-	= OMP_CLAUSE_DEPEND_SINK_NEGATIVE (decl);
+      OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (ret)
+	= OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl);
       return ret;
     }
   tree ret = tsubst_expr (decl, args, complain, in_decl,
@@ -17898,6 +17898,7 @@ tsubst_omp_clauses (tree clauses, enum c
 	case OMP_CLAUSE_COPYPRIVATE:
 	case OMP_CLAUSE_UNIFORM:
 	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE_DOACROSS:
 	case OMP_CLAUSE_AFFINITY:
 	case OMP_CLAUSE_FROM:
 	case OMP_CLAUSE_TO:
@@ -19414,7 +19415,7 @@ tsubst_expr (tree t, tree args, tsubst_f
       r = RECUR (OMP_DEPOBJ_DEPOBJ (t));
       if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node)
 	{
-	  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+	  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
 	  if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
 	    {
 	      tmp = tsubst_omp_clauses (OMP_DEPOBJ_CLAUSES (t), C_ORT_OMP,
@@ -19432,7 +19433,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 	}
       else
 	finish_omp_depobj (EXPR_LOCATION (t), r,
-			   OMP_CLAUSE_DEPEND_SOURCE,
+			   OMP_CLAUSE_DEPEND_INVALID,
 			   OMP_DEPOBJ_CLAUSES (t));
       break;
 
--- gcc/cp/semantics.cc.jj	2022-08-17 16:59:08.920548779 +0200
+++ gcc/cp/semantics.cc	2022-09-02 10:17:28.258285744 +0200
@@ -6477,13 +6477,13 @@ finish_omp_declare_simd_methods (tree t)
     }
 }
 
-/* Adjust sink depend clause to take into account pointer offsets.
+/* Adjust sink depend/doacross clause to take into account pointer offsets.
 
    Return TRUE if there was a problem processing the offset, and the
    whole clause should be removed.  */
 
 static bool
-cp_finish_omp_clause_depend_sink (tree sink_clause)
+cp_finish_omp_clause_doacross_sink (tree sink_clause)
 {
   tree t = OMP_CLAUSE_DECL (sink_clause);
   gcc_assert (TREE_CODE (t) == TREE_LIST);
@@ -7795,21 +7795,18 @@ finish_omp_clauses (tree clauses, enum c
 	    }
 	  goto handle_field_decl;
 
-	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE_DOACROSS:
 	  t = OMP_CLAUSE_DECL (c);
 	  if (t == NULL_TREE)
+	    break;
+	  if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
 	    {
-	      gcc_assert (OMP_CLAUSE_DEPEND_KIND (c)
-			  == OMP_CLAUSE_DEPEND_SOURCE);
-	      break;
-	    }
-	  if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
-	    {
-	      if (cp_finish_omp_clause_depend_sink (c))
+	      if (cp_finish_omp_clause_doacross_sink (c))
 		remove = true;
 	      break;
 	    }
-	  /* FALLTHRU */
+	  gcc_unreachable ();
+	case OMP_CLAUSE_DEPEND:
 	case OMP_CLAUSE_AFFINITY:
 	  t = OMP_CLAUSE_DECL (c);
 	  if (TREE_CODE (t) == TREE_LIST
--- gcc/fortran/trans-openmp.cc.jj	2022-07-26 10:32:23.799270266 +0200
+++ gcc/fortran/trans-openmp.cc	2022-09-01 16:28:06.688191566 +0200
@@ -2897,7 +2897,7 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
 			    }
 			  vec = tree_cons (addend, t, vec);
 			  if (neg)
-			    OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+			    OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
 			}
 		      if (n->next == NULL
 			  || n->next->u.depend_op != OMP_DEPEND_SINK)
@@ -2908,8 +2908,9 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
 		    continue;
 
 		  tree node = build_omp_clause (input_location,
-						OMP_CLAUSE_DEPEND);
-		  OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK;
+						OMP_CLAUSE_DOACROSS);
+		  OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK;
+		  OMP_CLAUSE_DOACROSS_DEPEND (node) = 1;
 		  OMP_CLAUSE_DECL (node) = nreverse (vec);
 		  omp_clauses = gfc_trans_add_clause (node, omp_clauses);
 		  continue;
@@ -4254,8 +4255,9 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
 
   if (clauses->depend_source)
     {
-      c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND);
-      OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE;
+      c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS);
+      OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE;
+      OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
 
--- gcc/testsuite/c-c++-common/gomp/doacross-2.c.jj	2020-01-12 11:54:37.013404356 +0100
+++ gcc/testsuite/c-c++-common/gomp/doacross-2.c	2022-09-02 18:13:24.093620768 +0200
@@ -7,13 +7,13 @@ foo (void)
   #pragma omp for ordered(1)
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered			/* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */
+      #pragma omp ordered
       ;
     }
   #pragma omp for ordered(1)
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered threads		/* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */
+      #pragma omp ordered threads
       ;
     }
 }
@@ -25,14 +25,20 @@ bar (void)
   #pragma omp for ordered
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered depend(source)	/* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
-      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
+      #pragma omp ordered depend(source)
+      #pragma omp ordered depend(sink: i - 1)
+    }
+  #pragma omp for ordered
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp ordered doacross(source:)
+      #pragma omp ordered doacross(sink: i - 1)
     }
   #pragma omp for
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered depend(source)	/* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
-      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
+      #pragma omp ordered depend(source)	/* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */
+      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */
     }
   #pragma omp for
   for (i = 0; i < 64; i++)
--- gcc/testsuite/c-c++-common/gomp/doacross-5.c.jj	2022-09-02 18:22:03.664570763 +0200
+++ gcc/testsuite/c-c++-common/gomp/doacross-5.c	2022-09-02 18:51:07.090930910 +0200
@@ -0,0 +1,94 @@
+void
+foo (int n)
+{
+  int i;
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(source:)
+      #pragma omp ordered doacross(sink: i - 2)
+    }
+}
+
+void
+bar (int n)
+{
+  int i, j;
+  #pragma omp for collapse(2) ordered(2)
+  for (i = 0; i < 8; i += n)
+    for (j = 0; j < 8; j += n)
+      {
+	#pragma omp ordered doacross(source:omp_cur_iteration)
+	#pragma omp ordered doacross(sink: i - 2, j + 2)
+      }
+}
+
+void
+baz (void)
+{
+  int i, j;
+  #pragma omp for ordered(1)
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp ordered			/* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */
+      ;
+      #pragma omp ordered doacross(source:)
+      #pragma omp ordered doacross(sink: i - 1)
+    }
+  #pragma omp for ordered
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp ordered doacross(source: omp_cur_iteration )
+      #pragma omp ordered doacross(sink: i - 1)
+      #pragma omp ordered threads		/* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */
+      ;
+    }
+  #pragma omp for ordered(2)
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < 8; j++)
+      {
+	#pragma omp ordered			/* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */
+	;
+      }
+  #pragma omp for ordered(2) collapse(1)
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < 8; j++)
+      {
+	#pragma omp ordered threads		/* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */
+	;
+      }
+}
+
+void
+qux (void)
+{
+  int i, j = 0;
+  #pragma omp for ordered linear(j)
+  for (i = 0; i < 64; i++)
+    {
+      ++j;
+      #pragma omp ordered
+      ;
+    }
+  #pragma omp for ordered linear(j)		/* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */
+  for (i = 0; i < 64; i++)
+    {
+      ++j;
+      #pragma omp ordered doacross(source:)
+      #pragma omp ordered doacross(sink:i-1)
+    }
+  #pragma omp for ordered(1) linear(j)
+  for (i = 0; i < 64; i++)
+    {
+      ++j;
+      #pragma omp ordered
+      ;
+    }
+  #pragma omp for ordered(1) linear(j)		/* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */
+  for (i = 0; i < 64; i++)
+    {
+      ++j;
+      #pragma omp ordered doacross(source:)
+      #pragma omp ordered doacross(sink:i-1)
+    }
+}
--- gcc/testsuite/c-c++-common/gomp/doacross-6.c.jj	2022-09-02 18:38:41.584036829 +0200
+++ gcc/testsuite/c-c++-common/gomp/doacross-6.c	2022-09-02 19:04:38.568922196 +0200
@@ -0,0 +1,74 @@
+void
+foo (int n)
+{
+  int i;
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(source)		/* { dg-error "expected ':' before '\\\)' token" } */
+    }
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(source:omp_current_iteration)	/* { dg-error "expected '\\\)' before 'omp_current_iteration'" } */
+    }
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(source:i - 2)	/* { dg-error "expected '\\\)' before 'i'" } */
+    }
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(sink)		/* { dg-error "expected ':' before '\\\)' token" } */
+    }
+}
+
+void
+bar (int n)
+{
+  int i;
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(sink:omp_current_iteration - 1)	/* { dg-error "'omp_current_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+    }									/* { dg-error "'omp_current_iteration' has not been declared" "" { target c++ } .-1 } */
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(sink:omp_cur_iteration)	/* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+    }								/* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */
+}
+
+void
+baz (int n)
+{
+  int i;
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(sink:omp_cur_iteration + 1)	/* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+    }								/* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */
+}
+
+void
+qux (int n)
+{
+  int i;
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(sink:omp_cur_iteration - (2 - 1))	/* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+    }								/* { dg-error "expected integer before '\\\(' token" "" { target *-*-* } .-1 } */
+}								/* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-2 } */
+								/* { dg-error "expected '\\\)' before '\\\(' token" "" { target c++ } .-3 } */
+void
+corge (int n)
+{
+  int i;
+  #pragma omp for ordered
+  for (i = 0; i < 8; i += n)
+    {
+      #pragma omp ordered doacross(sink:omp_cur_iteration - 1LL)	/* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+    }									/* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */
+}
--- gcc/testsuite/c-c++-common/gomp/nesting-2.c.jj	2021-08-17 09:29:41.408204898 +0200
+++ gcc/testsuite/c-c++-common/gomp/nesting-2.c	2022-09-02 17:37:47.252606491 +0200
@@ -160,7 +160,14 @@ foo (void)
   for (i = 0; i < 64; i++)
     #pragma omp parallel
     {
-      #pragma omp ordered depend(source)	/* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
-      #pragma omp ordered depend(sink: i - 1)	/* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+      #pragma omp ordered depend(source)	/* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered depend(sink: i - 1)	/* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */
+    }
+  #pragma omp for ordered(1)
+  for (i = 0; i < 64; i++)
+    #pragma omp parallel
+    {
+      #pragma omp ordered doacross(source:)	/* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered doacross(sink: i - 1)	/* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */
     }
 }
--- gcc/testsuite/c-c++-common/gomp/ordered-3.c.jj	2020-01-12 11:54:37.014404341 +0100
+++ gcc/testsuite/c-c++-common/gomp/ordered-3.c	2022-09-02 17:47:30.751700196 +0200
@@ -47,29 +47,53 @@ foo (void)
       #pragma omp ordered threads, simd, threads, simd	/* { dg-error "too many .threads. clauses" } */
       ;	/* { dg-error "too many .simd. clauses" "" { target *-*-* } .-1 } */
     }
-  #pragma omp for simd ordered(1)	/* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp for simd. construct" } */
+  #pragma omp for simd ordered(1)
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
-      #pragma omp ordered depend(source)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered depend(source)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
     }
-  #pragma omp parallel for simd ordered(1)	/* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp parallel for simd. construct" } */
+  #pragma omp for simd ordered(1)
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
-      #pragma omp ordered depend(source)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+      #pragma omp ordered doacross(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered doacross(source:omp_cur_iteration)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+    }
+  #pragma omp parallel for simd ordered(1)
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered depend(source)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+    }
+  #pragma omp parallel for simd ordered(1)
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp ordered doacross(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered doacross(source:)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+    }
+  #pragma omp parallel for ordered
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp ordered depend(sink: i - 1)
+      #pragma omp ordered depend(source)
     }
   #pragma omp parallel for ordered
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
-      #pragma omp ordered depend(source)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+      #pragma omp ordered doacross(sink: i - 1)
+      #pragma omp ordered doacross(source:)
+    }
+  #pragma omp parallel for
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered depend(source)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
     }
   #pragma omp parallel for
   for (i = 0; i < 64; i++)
     {
-      #pragma omp ordered depend(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
-      #pragma omp ordered depend(source)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+      #pragma omp ordered doacross(sink: i - 1)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+      #pragma omp ordered doacross(source:)	/* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
     }
 }
 
--- gcc/testsuite/c-c++-common/gomp/sink-3.c.jj	2020-01-12 11:54:37.016404311 +0100
+++ gcc/testsuite/c-c++-common/gomp/sink-3.c	2022-09-02 18:09:01.480185433 +0200
@@ -14,7 +14,7 @@ foo ()
   for (i=0; i < 100; ++i)
     {
 #pragma omp ordered depend(sink:poo-1,paa+1) /* { dg-error "poo.*declared.*paa.*declared" } */
-    bar(&i);				     /* { dg-error "may not be closely nested" "" { target *-*-* } .-1 } */
+    bar(&i);				     /* { dg-error "must not have the same binding region" "" { target *-*-* } .-1 } */
 #pragma omp ordered depend(source)
     }
 }
--- gcc/testsuite/gfortran.dg/gomp/nesting-2.f90.jj	2021-08-17 16:34:31.610102996 +0200
+++ gcc/testsuite/gfortran.dg/gomp/nesting-2.f90	2022-09-02 18:15:10.209180367 +0200
@@ -158,8 +158,8 @@ subroutine foo
   !$omp do ordered(1)
   do i = 0, 63
     !$omp parallel
-      !$omp ordered depend(source)	! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" }
-      !$omp ordered depend(sink: i - 1)	! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" }
+      !$omp ordered depend(source)	! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" }
+      !$omp ordered depend(sink: i - 1)	! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" }
     !$omp end parallel
   end do
 end
