[gomp5] Add #pragma omp depobj support

Message ID 20180628181536.GF7166@tucnak
State New
Headers show
Series
  • [gomp5] Add #pragma omp depobj support
Related show

Commit Message

Jakub Jelinek June 28, 2018, 6:15 p.m.
Hi!

This patch adds #pragma omp depobj support, so that the task dependencies
can be built at one spot and used later on from the omp_depend_t structure
that has all the necessary information (object address and dependence type)
later on.

In addition this fixes some problems in the depend clause handling, e.g.
handles references correctly, or e.g. C++ x ? y : z lvalues, --x lvalues
etc.  Mutexinoutset is also propagated to the library, which right now
still handles it conservatively as inout/out.

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

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

	* tree-core.h (enum omp_clause_depend_kind): Add
	OMP_CLAUSE_DEPEND_UNSPECIFIED.
	* gimplify.c (gimplify_omp_depend): If there are any
	OMP_CLAUSE_DEPEND_UNSPECIFIED or OMP_CLAUSE_DEPEND_MUTEXINOUTSET
	depend clauses, use a new array format.
	* omp-low.c (lower_depend_clauses): Likewise.
	* tree-pretty-print.c (dump_omp_clause): Handle
	OMP_CLAUSE_DEPEND_UNSPECIFIED.
gcc/c-family/
	* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_DEPOBJ.
	* c-pragma.c (omp_pragmas): Likewise.
	* c-common.h (c_omp_depend_t_p, c_finish_omp_depobj): Declare.
	* c-omp.c (c_omp_depend_t_p, c_finish_omp_depobj): New functions.
gcc/c/
	* c-parser.c (c_parser_omp_depobj): New function.
	(c_parser_pragma): Handle PRAGMA_OMP_DEPOBJ.
	(c_parser_omp_iterators): Return error_mark_node instead of NULL.
	(c_parser_omp_clause_depend): Make dependence-type optional.
	* c-typeck.c (c_finish_omp_clauses): Handle depend clause with
	OMP_CLAUSE_DEPEND_UNSPECIFIED.  Diagnose bit-fields.  Require
	omp_depend_t type for OMP_CLAUSE_DEPEND_UNSPECIFIED kinds and
	some different type for other kinds.  Use build_unary_op with
	ADDR_EXPR and build_indirect_ref instead of c_mark_addressable.
gcc/cp/
	* parser.c (cp_parser_omp_var_list_no_open): Fix up depend clause
	error recovery.
	(cp_parser_omp_iterators): Return error_mark_node instead of NULL.
	(cp_parser_omp_clause_depend): Make dependence-type optional.
	(cp_parser_omp_depobj): New function.
	(cp_parser_pragma): Handle PRAGMA_OMP_DEPOBJ.
	* cp-tree.h (OMP_DEPOBJ_DEPOBJ, OMP_DEPOBJ_CLAUSES): Define.
	(finish_omp_depobj): Declare.
	* cp-tree.def (OMP_DEPOBJ): New tree code.
	* semantics.c (finish_omp_clauses): Handle depend clause with
	OMP_CLAUSE_DEPEND_UNSPECIFIED.  Diagnose bit-fields.  Require
	omp_depend_t type for OMP_CLAUSE_DEPEND_UNSPECIFIED kinds and
	some different type for other kinds.  Use cp_build_addr_expr
	and cp_build_indirect_ref instead of cxx_mark_addressable.
	(finish_omp_depobj): New function.
	* pt.c (tsubst_expr): Handle OMP_DEPOBJ.
	* cp-objcp-common.c (cp_common_init_ts): Likewise.
	* constexpr.c (potential_constant_expression_1): Likewise.
	* lex.c (cxx_init): Likewise.
	* dump.c (cp_dump_tree): Likewise.
	* cxx-pretty-print.c (cxx_pretty_printer::statement): Likewise.
gcc/testsuite/
	* c-c++-common/gomp/depend-6.c: Add test for bit-field in depend
	clause.
	* c-c++-common/gomp/depend-iterator-2.c: Adjust for dependence-type
	being optional.
	* c-c++-common/gomp/depobj-1.c: New test.
	* g++.dg/gomp/depend-iterator-2.C: Adjust for dependence-type being
	optional.
	* g++.dg/gomp/depobj-1.C: New test.
include/
	* gomp-constants.h (GOMP_DEPEND_IN, GOMP_DEPEND_OUT,
	GOMP_DEPEND_INOUT, GOMP_DEPEND_MUTEXINOUTSET): Define.
libgomp/
	* omp.h.in (omp_depend_t): New typedef.
	* task.c (gomp_task_handle_depend): Handle new depend array format
	in addition to the old.  Handle mutexinoutset kinds the same as
	inout for now, handle unspecified kinds.
	(gomp_task_maybe_wait_for_dependencies): Likewise.
	(gomp_create_target_task): Handle new depend array format count in
	addition to the old.
	(GOMP_task): Likewise.  Adjust function comment.
	* testsuite/libgomp.c-c++-common/depend-iterator-2.c: New test.
	* testsuite/libgomp.c-c++-common/depobj-1.c: New test.
	* testsuite/libgomp.c++/depend-1.C: New test.
	* testsuite/libgomp.c++/depobj-1.C: New test.


	Jakub

Patch

--- gcc/tree-core.h.jj	2018-06-05 15:00:56.357957856 +0200
+++ gcc/tree-core.h	2018-06-26 11:46:03.951421363 +0200
@@ -1416,6 +1416,7 @@  struct GTY(()) tree_constructor {
 
 enum omp_clause_depend_kind
 {
+  OMP_CLAUSE_DEPEND_UNSPECIFIED,
   OMP_CLAUSE_DEPEND_IN,
   OMP_CLAUSE_DEPEND_OUT,
   OMP_CLAUSE_DEPEND_INOUT,
--- gcc/gimplify.c.jj	2018-06-18 19:07:09.152186493 +0200
+++ gcc/gimplify.c	2018-06-27 11:33:45.353027093 +0200
@@ -7566,10 +7566,11 @@  gimplify_omp_depend (tree *list_p, gimpl
 {
   tree c;
   gimple *g;
-  size_t n[2] = { 0, 0 };
-  tree counts[2] = { NULL_TREE, NULL_TREE };
+  size_t n[4] = { 0, 0, 0, 0 };
+  bool unused[4];
+  tree counts[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
   tree last_iter = NULL_TREE, last_count = NULL_TREE;
-  size_t i;
+  size_t i, j;
   location_t first_loc = UNKNOWN_LOCATION;
 
   for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
@@ -7578,13 +7579,18 @@  gimplify_omp_depend (tree *list_p, gimpl
 	switch (OMP_CLAUSE_DEPEND_KIND (c))
 	  {
 	  case OMP_CLAUSE_DEPEND_IN:
-	    i = 0;
+	    i = 2;
 	    break;
 	  case OMP_CLAUSE_DEPEND_OUT:
 	  case OMP_CLAUSE_DEPEND_INOUT:
+	    i = 0;
+	    break;
 	  case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
 	    i = 1;
 	    break;
+	  case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+	    i = 3;
+	    break;
 	  case OMP_CLAUSE_DEPEND_SOURCE:
 	  case OMP_CLAUSE_DEPEND_SINK:
 	    continue;
@@ -7679,10 +7685,16 @@  gimplify_omp_depend (tree *list_p, gimpl
 	else
 	  n[i]++;
       }
-  if (counts[0] == NULL_TREE && counts[1] == NULL_TREE)
+  for (i = 0; i < 4; i++)
+    if (counts[i])
+      break;
+  if (i == 4)
     return 0;
-  for (i = 0; i < 2; i++)
+
+  tree total = size_zero_node;
+  for (i = 0; i < 4; i++)
     {
+      unused[i] = counts[i] == NULL_TREE && n[i] == 0;
       if (counts[i] == NULL_TREE)
 	counts[i] = size_zero_node;
       if (n[i])
@@ -7690,17 +7702,19 @@  gimplify_omp_depend (tree *list_p, gimpl
       if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
 			 fb_rvalue) == GS_ERROR)
 	return 2;
+      total = size_binop (PLUS_EXPR, total, counts[i]);
     }
 
-  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));
+  bool is_old = unused[1] && unused[3];
+  tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
+			     size_int (is_old ? 1 : 4));
+  tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
   tree array = create_tmp_var_raw (type);
   TREE_ADDRESSABLE (array) = 1;
-  if (TREE_CODE (totalp1) != INTEGER_CST)
+  if (TREE_CODE (totalpx) != INTEGER_CST)
     {
       if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
 	gimplify_type_sizes (TREE_TYPE (array), pre_p);
@@ -7721,21 +7735,52 @@  gimplify_omp_depend (tree *list_p, gimpl
     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]);
+  tree tem;
+  if (!is_old)
+    {
+      tem = build2 (MODIFY_EXPR, void_type_node, r,
+		    build_int_cst (ptr_type_node, 0));
+      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,
+		fold_convert (ptr_type_node, total));
   gimplify_and_add (tem, pre_p);
+  for (i = 1; i < (is_old ? 2 : 4); i++)
+    {
+      r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
+		  NULL_TREE, NULL_TREE);
+      tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
+      gimplify_and_add (tem, pre_p);
+    }
 
-  tree cnts[2];
-  for (i = 0; i < 2; i++)
+  tree cnts[4];
+  for (j = 4; j; j--)
+    if (!unused[j - 1])
+      break;
+  for (i = 0; i < 4; i++)
     {
+      if (i && (i >= j || unused[i - 1]))
+	{
+	  cnts[i] = cnts[i - 1];
+	  continue;
+	}
       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)));
+      if (i == 0)
+	g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
+      else
+	{
+	  tree t;
+	  if (is_old)
+	    t = size_binop (PLUS_EXPR, counts[0], size_int (2));
+	  else
+	    t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
+	  if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
+	      == GS_ERROR)
+	    return 2;
+	  g = gimple_build_assign (cnts[i], t);
+	}
       gimple_seq_add_stmt (pre_p, g);
     }
 
@@ -7748,13 +7793,18 @@  gimplify_omp_depend (tree *list_p, gimpl
 	switch (OMP_CLAUSE_DEPEND_KIND (c))
 	  {
 	  case OMP_CLAUSE_DEPEND_IN:
-	    i = 0;
+	    i = 2;
 	    break;
 	  case OMP_CLAUSE_DEPEND_OUT:
 	  case OMP_CLAUSE_DEPEND_INOUT:
+	    i = 0;
+	    break;
 	  case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
 	    i = 1;
 	    break;
+	  case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+	    i = 3;
+	    break;
 	  case OMP_CLAUSE_DEPEND_SOURCE:
 	  case OMP_CLAUSE_DEPEND_SINK:
 	    continue;
@@ -7897,14 +7947,34 @@  gimplify_omp_depend (tree *list_p, gimpl
       }
   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))));
+  tree cond = boolean_false_node;
+  if (is_old)
+    {
+      if (!unused[0])
+	cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
+			   size_binop_loc (first_loc, PLUS_EXPR, counts[0],
+					   size_int (2)));
+      if (!unused[2])
+	cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
+			   build2_loc (first_loc, NE_EXPR, boolean_type_node,
+				       cnts[2],
+				       size_binop_loc (first_loc, PLUS_EXPR,
+						       totalpx,
+						       size_int (1))));
+    }
+  else
+    {
+      tree prev = size_int (5);
+      for (i = 0; i < 4; i++)
+	{
+	  if (unused[i])
+	    continue;
+	  prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
+	  cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
+			     build2_loc (first_loc, NE_EXPR, boolean_type_node,
+					 cnts[i], unshare_expr (prev)));
+	}
+    }
   tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
 		    build_call_expr_loc (first_loc,
 					 builtin_decl_explicit (BUILT_IN_TRAP),
--- gcc/tree-pretty-print.c.jj	2018-06-18 19:07:09.152186493 +0200
+++ gcc/tree-pretty-print.c	2018-06-26 11:46:03.842421284 +0200
@@ -674,6 +674,9 @@  dump_omp_clause (pretty_printer *pp, tre
       pp_string (pp, "depend(");
       switch (OMP_CLAUSE_DEPEND_KIND (clause))
 	{
+	case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+	  name = NULL;
+	  break;
 	case OMP_CLAUSE_DEPEND_IN:
 	  name = "in";
 	  break;
@@ -727,8 +730,11 @@  dump_omp_clause (pretty_printer *pp, tre
 	    pp_colon (pp);
 	    t = TREE_VALUE (t);
 	  }
-	pp_string (pp, name);
-	pp_colon (pp);
+	if (name)
+	  {
+	    pp_string (pp, name);
+	    pp_colon (pp);
+	  }
 	dump_generic_node (pp, t, spc, flags, false);
 	pp_right_paren (pp);
       }
--- gcc/omp-low.c.jj	2018-06-19 08:24:31.960876918 +0200
+++ gcc/omp-low.c	2018-06-26 19:28:36.560929535 +0200
@@ -7351,7 +7351,7 @@  lower_depend_clauses (tree *pclauses, gi
 {
   tree c, clauses;
   gimple *g;
-  size_t n_in = 0, n_out = 0, idx = 2, i;
+  size_t cnt[4] = { 0, 0, 0, 0 }, idx = 2, i;
 
   clauses = omp_find_clause (*pclauses, OMP_CLAUSE_DEPEND);
   gcc_assert (clauses);
@@ -7363,12 +7363,17 @@  lower_depend_clauses (tree *pclauses, gi
 	  /* Lowering already done at gimplification.  */
 	  return;
 	case OMP_CLAUSE_DEPEND_IN:
-	  n_in++;
+	  cnt[2]++;
 	  break;
 	case OMP_CLAUSE_DEPEND_OUT:
 	case OMP_CLAUSE_DEPEND_INOUT:
+	  cnt[0]++;
+	  break;
 	case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
-	  n_out++;
+	  cnt[1]++;
+	  break;
+	case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+	  cnt[3]++;
 	  break;
 	case OMP_CLAUSE_DEPEND_SOURCE:
 	case OMP_CLAUSE_DEPEND_SINK:
@@ -7376,25 +7381,61 @@  lower_depend_clauses (tree *pclauses, gi
 	default:
 	  gcc_unreachable ();
 	}
-  tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
+  if (cnt[1] || cnt[3])
+    idx = 5;
+  size_t total = cnt[0] + cnt[1] + cnt[2] + cnt[3];
+  tree type = build_array_type_nelts (ptr_type_node, total + idx);
   tree array = create_tmp_var (type);
   TREE_ADDRESSABLE (array) = 1;
   tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
 		   NULL_TREE);
-  g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
-  gimple_seq_add_stmt (iseq, g);
-  r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
-	      NULL_TREE);
-  g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
+  if (idx == 5)
+    {
+      g = gimple_build_assign (r, build_int_cst (ptr_type_node, 0));
+      gimple_seq_add_stmt (iseq, g);
+      r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
+		  NULL_TREE);
+    }
+  g = gimple_build_assign (r, build_int_cst (ptr_type_node, total));
   gimple_seq_add_stmt (iseq, g);
-  for (i = 0; i < 2; i++)
+  for (i = 0; i < (idx == 5 ? 3 : 1); i++)
+    {
+      r = build4 (ARRAY_REF, ptr_type_node, array,
+		  size_int (i + 1 + (idx == 5)), NULL_TREE, NULL_TREE);
+      g = gimple_build_assign (r, build_int_cst (ptr_type_node, cnt[i]));
+      gimple_seq_add_stmt (iseq, g);
+    }
+  for (i = 0; i < 4; i++)
     {
-      if ((i ? n_in : n_out) == 0)
+      if (cnt[i] == 0)
 	continue;
       for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
-	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-	    && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
+	if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+	  continue;
+	else
 	  {
+	    switch (OMP_CLAUSE_DEPEND_KIND (c))
+	      {
+	      case OMP_CLAUSE_DEPEND_IN:
+		if (i != 2)
+		  continue;
+		break;
+	      case OMP_CLAUSE_DEPEND_OUT:
+	      case OMP_CLAUSE_DEPEND_INOUT:
+		if (i != 0)
+		  continue;
+		break;
+	      case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+		if (i != 1)
+		  continue;
+		break;
+	      case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+		if (i != 3)
+		  continue;
+		break;
+	      default:
+		gcc_unreachable ();
+	      }
 	    tree t = OMP_CLAUSE_DECL (c);
 	    t = fold_convert (ptr_type_node, t);
 	    gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
--- gcc/c-family/c-pragma.h.jj	2018-05-24 18:39:36.408008391 +0200
+++ gcc/c-family/c-pragma.h	2018-06-26 11:46:03.898421325 +0200
@@ -47,6 +47,7 @@  enum pragma_kind {
   PRAGMA_OMP_CANCELLATION_POINT,
   PRAGMA_OMP_CRITICAL,
   PRAGMA_OMP_DECLARE,
+  PRAGMA_OMP_DEPOBJ,
   PRAGMA_OMP_DISTRIBUTE,
   PRAGMA_OMP_END_DECLARE_TARGET,
   PRAGMA_OMP_FLUSH,
--- gcc/c-family/c-pragma.c.jj	2018-05-30 10:16:26.973224443 +0200
+++ gcc/c-family/c-pragma.c	2018-06-26 11:46:03.937421353 +0200
@@ -1286,6 +1286,7 @@  static const struct omp_pragma_def omp_p
   { "cancel", PRAGMA_OMP_CANCEL },
   { "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
   { "critical", PRAGMA_OMP_CRITICAL },
+  { "depobj", PRAGMA_OMP_DEPOBJ },
   { "end", PRAGMA_OMP_END_DECLARE_TARGET },
   { "flush", PRAGMA_OMP_FLUSH },
   { "master", PRAGMA_OMP_MASTER },
--- gcc/c-family/c-common.h.jj	2018-06-19 10:42:21.289381950 +0200
+++ gcc/c-family/c-common.h	2018-06-26 15:06:55.976139163 +0200
@@ -1149,6 +1149,9 @@  extern void c_finish_omp_barrier (locati
 extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
 				 tree, tree, tree, tree, tree, bool,
 				 enum omp_memory_order, bool = false);
+extern bool c_omp_depend_t_p (tree);
+extern void c_finish_omp_depobj (location_t, tree, enum omp_clause_depend_kind,
+				 tree);
 extern void c_finish_omp_flush (location_t, int);
 extern void c_finish_omp_taskwait (location_t);
 extern void c_finish_omp_taskyield (location_t);
--- gcc/c-family/c-omp.c.jj	2018-06-19 10:42:21.290381951 +0200
+++ gcc/c-family/c-omp.c	2018-06-28 12:52:35.420378922 +0200
@@ -28,6 +28,7 @@  along with GCC; see the file COPYING3.
 #include "c-common.h"
 #include "gimple-expr.h"
 #include "c-pragma.h"
+#include "stringpool.h"
 #include "omp-general.h"
 #include "gomp-constants.h"
 #include "memmodel.h"
@@ -417,6 +418,153 @@  c_finish_omp_atomic (location_t loc, enu
 }
 
 
+/* Return true if TYPE is the implementation's omp_depend_t.  */
+
+bool
+c_omp_depend_t_p (tree type)
+{
+  type = TYPE_MAIN_VARIANT (type);
+  return (TREE_CODE (type) == RECORD_TYPE
+	  && TYPE_NAME (type)
+	  && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+	       ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
+	      == get_identifier ("omp_depend_t"))
+	  && (!TYPE_CONTEXT (type)
+	      || TREE_CODE (TYPE_CONTEXT (type)) == TRANSLATION_UNIT_DECL)
+	  && COMPLETE_TYPE_P (type)
+	  && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+	  && !compare_tree_int (TYPE_SIZE (type),
+				2 * tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
+}
+
+
+/* Complete a #pragma omp depobj construct.  LOC is the location of the
+   #pragma.  */
+
+void
+c_finish_omp_depobj (location_t loc, tree depobj,
+		     enum omp_clause_depend_kind kind, tree clause)
+{
+  tree t = NULL_TREE;
+  if (!error_operand_p (depobj))
+    {
+      if (!c_omp_depend_t_p (TREE_TYPE (depobj)))
+	{
+	  error_at (EXPR_LOC_OR_LOC (depobj, loc),
+		    "type of %<depobj%> expression is not %<omp_depend_t%>");
+	  depobj = error_mark_node;
+	}
+      else if (TYPE_READONLY (TREE_TYPE (depobj)))
+	{
+	  error_at (EXPR_LOC_OR_LOC (depobj, loc),
+		    "%<const%> qualified %<depobj%> expression");
+	  depobj = error_mark_node;
+	}
+    }
+  else
+    depobj = error_mark_node;
+
+  if (clause == error_mark_node)
+    return;
+
+  if (clause)
+    {
+      gcc_assert (TREE_CODE (clause) == OMP_CLAUSE
+		  && 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%> "
+		  "construct");
+      switch (OMP_CLAUSE_DEPEND_KIND (clause))
+	{
+	case OMP_CLAUSE_DEPEND_UNSPECIFIED:
+	  error_at (OMP_CLAUSE_LOCATION (clause),
+		    "dependence type must be 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:
+	case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+	  kind = OMP_CLAUSE_DEPEND_KIND (clause);
+	  t = OMP_CLAUSE_DECL (clause);
+	  gcc_assert (t);
+	  if (TREE_CODE (t) == TREE_LIST
+	      && TREE_PURPOSE (t)
+	      && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+	    {
+	      error_at (OMP_CLAUSE_LOCATION (clause),
+			"%<iterator%> modifier may not be specified on "
+			"%<depobj%> construct");
+	      return;
+	    }
+	  if (TREE_CODE (t) == COMPOUND_EXPR)
+	    {
+	      tree t1 = build_fold_addr_expr (TREE_OPERAND (t, 1));
+	      t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
+			  t1);
+	    }
+	  else
+	    t = build_fold_addr_expr (t);
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+    }
+  else
+    gcc_assert (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED);
+
+  if (depobj == error_mark_node)
+    return;
+
+  depobj = build_fold_addr_expr_loc (EXPR_LOC_OR_LOC (depobj, loc), depobj);
+  tree dtype
+    = build_pointer_type_for_mode (ptr_type_node, TYPE_MODE (ptr_type_node),
+				   true);
+  depobj = fold_convert (dtype, depobj);
+  tree r;
+  if (clause)
+    {
+      depobj = save_expr (depobj);
+      r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
+      add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
+    }
+  int k;
+  switch (kind)
+    {
+    case OMP_CLAUSE_DEPEND_IN:
+      k = GOMP_DEPEND_IN;
+      break;
+    case OMP_CLAUSE_DEPEND_OUT:
+      k = GOMP_DEPEND_OUT;
+      break;
+    case OMP_CLAUSE_DEPEND_INOUT:
+      k = GOMP_DEPEND_INOUT;
+      break;
+    case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+      k = GOMP_DEPEND_MUTEXINOUTSET;
+      break;
+    case OMP_CLAUSE_DEPEND_LAST:
+      k = -1;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  t = build_int_cst (ptr_type_node, k);
+  depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
+		       TYPE_SIZE_UNIT (ptr_type_node));
+  r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
+  add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
+}
+
+
 /* Complete a #pragma omp flush construct.  We don't do anything with
    the variable list that the syntax allows.  LOC is the location of
    the #pragma.  */
--- gcc/c/c-parser.c.jj	2018-06-19 10:42:21.288381950 +0200
+++ gcc/c/c-parser.c	2018-06-28 10:06:16.079468470 +0200
@@ -1446,6 +1446,7 @@  static void c_parser_oacc_update (c_pars
 static void c_parser_omp_construct (c_parser *, bool *);
 static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
+static void c_parser_omp_depobj (c_parser *);
 static void c_parser_omp_flush (c_parser *);
 static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
 				   tree, tree *, bool *);
@@ -10999,6 +11000,15 @@  c_parser_pragma (c_parser *parser, enum
       c_parser_omp_barrier (parser);
       return false;
 
+    case PRAGMA_OMP_DEPOBJ:
+      if (context != pragma_compound)
+	{
+	  construct = "omp depobj";
+	  goto in_compound;
+	}
+      c_parser_omp_depobj (parser);
+      return false;
+
     case PRAGMA_OMP_FLUSH:
       if (context != pragma_compound)
 	{
@@ -13900,7 +13910,7 @@  c_parser_omp_iterators (c_parser *parser
   while (1);
 
   parens.skip_until_found_close (parser);
-  return ret;
+  return ret ? ret : error_mark_node;
 }
 
 /* OpenMP 4.0:
@@ -13918,7 +13928,7 @@  static tree
 c_parser_omp_clause_depend (c_parser *parser, tree list)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
-  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
   tree nl, c, iterators = NULL_TREE;
 
   matching_parens parens;
@@ -13928,9 +13938,31 @@  c_parser_omp_clause_depend (c_parser *pa
   do
     {
       if (c_parser_next_token_is_not (parser, CPP_NAME))
-	goto invalid_kind;
+	break;
 
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp ("iterator", p) == 0
+	  && iterators == NULL_TREE
+	  && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
+	{
+	  /* FIXME: if depend kind remains optional, this is ambiguous
+	     and we'd need to do tentative parsing to distinguish between
+	     valid iterator modifier and just normal expression starting
+	     with iterator ( tokens.  Not doing it right now, as I hope
+	     it will become mandatory.  */
+	  iterators = c_parser_omp_iterators (parser);
+	  c_parser_require (parser, CPP_COLON, "expected %<:%>");
+	  continue;
+	}
+      if (strcmp ("source", p) == 0
+	  && c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN)
+	{
+	  /* FIXME: this is another ambiguity.  */
+	  kind = OMP_CLAUSE_DEPEND_SOURCE;
+	  break;
+	}
+      if (c_parser_peek_2nd_token (parser)->type != CPP_COLON)
+	break;
       if (strcmp ("in", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_IN;
       else if (strcmp ("inout", p) == 0)
@@ -13939,23 +13971,16 @@  c_parser_omp_clause_depend (c_parser *pa
 	kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
       else if (strcmp ("out", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_OUT;
-      else if (strcmp ("source", p) == 0)
-	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;
     }
   while (1);
 
-  c_parser_consume_token (parser);
+  if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED)
+    c_parser_consume_token (parser);
 
   if (iterators
       && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
@@ -13976,7 +14001,8 @@  c_parser_omp_clause_depend (c_parser *pa
       return c;
     }
 
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+  if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED
+      && !c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     goto resync_fail;
 
   if (kind == OMP_CLAUSE_DEPEND_SINK)
@@ -16106,6 +16132,115 @@  c_parser_omp_critical (location_t loc, c
   return c_finish_omp_critical (loc, stmt, name, clauses);
 }
 
+/* OpenMP 5.0:
+   # pragma omp depobj ( depobj ) depobj-clause new-line
+
+   depobj-clause:
+     depend (dependence-type : locator)
+     destroy
+     update (dependence-type)
+
+   dependence-type:
+     in
+     out
+     inout
+     mutexinout  */
+
+static void
+c_parser_omp_depobj (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return;
+    }
+
+  tree depobj = c_parser_expr_no_commas (parser, NULL).value;
+  if (depobj != error_mark_node)
+    {
+      if (!lvalue_p (depobj))
+	{
+	  error_at (EXPR_LOC_OR_LOC (depobj, loc),
+		    "%<depobj%> expression is not lvalue expression");
+	  depobj = error_mark_node;
+	}
+      else
+	{
+	  tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
+				      depobj, false);
+	  if (addr == error_mark_node)
+	    depobj = error_mark_node;
+	  else
+	    depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
+					 addr, RO_UNARY_STAR);
+	}
+    }
+
+  parens.skip_until_found_close (parser);
+  tree clause = NULL_TREE;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
+  location_t c_loc = c_parser_peek_token (parser)->location;
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+      c_parser_consume_token (parser);
+      if (!strcmp ("depend", p))
+	{
+	  clause = c_parser_omp_clause_depend (parser, NULL_TREE);
+	  clause = c_finish_omp_clauses (clause, C_ORT_OMP);
+	  if (!clause)
+	    clause = error_mark_node;
+	}
+      else if (!strcmp ("destroy", p))
+	kind = OMP_CLAUSE_DEPEND_LAST;
+      else if (!strcmp ("update", p))
+	{
+	  matching_parens c_parens;
+	  if (c_parens.require_open (parser))
+	    {
+	      location_t c2_loc = c_parser_peek_token (parser)->location;
+	      if (c_parser_next_token_is (parser, CPP_NAME))
+		{
+		  const char *p2
+		    = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+		  c_parser_consume_token (parser);
+		  if (!strcmp ("in", p2))
+		    kind = OMP_CLAUSE_DEPEND_IN;
+		  else if (!strcmp ("out", p2))
+		    kind = OMP_CLAUSE_DEPEND_OUT;
+		  else if (!strcmp ("inout", p2))
+		    kind = OMP_CLAUSE_DEPEND_INOUT;
+		  else if (!strcmp ("mutexinoutset", p2))
+		    kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+		}
+	      if (kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+		{
+		  clause = error_mark_node;
+		  error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
+				    "%<mutexinoutset%>");
+		}
+	      c_parens.skip_until_found_close (parser);
+	    }
+	  else
+	    clause = error_mark_node;
+	}
+    }
+  if (!clause && kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+    {
+      clause = error_mark_node;
+      error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
+    }
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+
 /* OpenMP 2.5:
    # pragma omp flush flush-vars[opt] new-line
 
--- gcc/c/c-typeck.c.jj	2018-06-13 18:21:54.220430042 +0200
+++ gcc/c/c-typeck.c	2018-06-28 13:59:50.451669508 +0200
@@ -13771,6 +13771,14 @@  c_finish_omp_clauses (tree clauses, enum
 	    {
 	      if (handle_omp_array_sections (c, ort))
 		remove = true;
+	      else if (OMP_CLAUSE_DEPEND_KIND (c)
+		       == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+		{
+		  error_at (OMP_CLAUSE_LOCATION (c),
+			    "%<depend%> clause without dependence type "
+			    "on array section");
+		  remove = true;
+		}
 	      break;
 	    }
 	  if (t == error_mark_node)
@@ -13782,8 +13790,51 @@  c_finish_omp_clauses (tree clauses, enum
 			"%<depend%> clause", t);
 	      remove = true;
 	    }
-	  else if (!c_mark_addressable (t))
-	    remove = true;
+	  else if (TREE_CODE (t) == COMPONENT_REF
+		   && DECL_C_BIT_FIELD (TREE_OPERAND (t, 1)))
+	    {
+	      error_at (OMP_CLAUSE_LOCATION (c),
+			"bit-field %qE in %qs clause", t, "depend");
+	      remove = true;
+	    }
+	  else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+	    {
+	      if (!c_omp_depend_t_p (TREE_TYPE (t)))
+		{
+		  error_at (OMP_CLAUSE_LOCATION (c),
+			    "%qE does not have %<omp_depend_t%> type in "
+			    "%<depend%> clause without dependence type", t);
+		  remove = true;
+		}
+	    }
+	  else if (c_omp_depend_t_p (TREE_TYPE (t)))
+	    {
+	      error_at (OMP_CLAUSE_LOCATION (c),
+			"%qE should not have %<omp_depend_t%> type in "
+			"%<depend%> clause with dependence type", t);
+	      remove = true;
+	    }
+	  if (!remove)
+	    {
+	      tree addr = build_unary_op (OMP_CLAUSE_LOCATION (c), ADDR_EXPR,
+					  t, false);
+	      if (addr == error_mark_node)
+		remove = true;
+	      else
+		{
+		  t = build_indirect_ref (OMP_CLAUSE_LOCATION (c), addr,
+					  RO_UNARY_STAR);
+		  if (t == error_mark_node)
+		    remove = true;
+		  else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+			   && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+			   && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+			       == TREE_VEC))
+		    TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+		  else
+		    OMP_CLAUSE_DECL (c) = t;
+		}
+	    }
 	  break;
 
 	case OMP_CLAUSE_MAP:
--- gcc/cp/parser.c.jj	2018-06-19 10:42:21.296381957 +0200
+++ gcc/cp/parser.c	2018-06-28 12:29:49.355395472 +0200
@@ -31619,8 +31619,13 @@  cp_parser_omp_var_list_no_open (cp_parse
 	  else
 	    decl = name;
 	  if (decl == error_mark_node)
-	    cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
-					 token->location);
+	    {
+	      if (kind == OMP_CLAUSE_DEPEND
+		  && cp_parser_simulate_error (parser))
+		goto depend_lvalue;
+	      cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
+					   token->location);
+	    }
 	}
       if (decl == error_mark_node)
 	;
@@ -33708,7 +33713,7 @@  cp_parser_omp_iterators (cp_parser *pars
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  return ret;
+  return ret ? ret : error_mark_node;
 }
 
 /* OpenMP 4.0:
@@ -33726,7 +33731,7 @@  static tree
 cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
 {
   tree nlist, c, iterators = NULL_TREE;
-  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
 
   matching_parens parens;
   if (!parens.require_open (parser))
@@ -33735,11 +33740,44 @@  cp_parser_omp_clause_depend (cp_parser *
   do
     {
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
-	goto invalid_kind;
+	break;
 
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
 
+      if (strcmp ("iterator", p) == 0
+	  && iterators == NULL_TREE
+	  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+	{
+	  cp_lexer_save_tokens (parser->lexer);
+	  cp_lexer_consume_token (parser->lexer);
+	  cp_lexer_consume_token (parser->lexer);
+	  bool is_iter
+	    = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
+						      /*consume_paren=*/true)
+	       && cp_lexer_next_token_is (parser->lexer, CPP_COLON));
+
+	  /* Roll back the tokens we skipped.  */
+	  cp_lexer_rollback_tokens (parser->lexer);
+
+	  if (is_iter)
+	    {
+	      begin_scope (sk_omp, NULL);
+	      iterators = cp_parser_omp_iterators (parser);
+	      cp_parser_require (parser, CPP_COLON, RT_COLON);
+	      continue;
+	    }
+	}
+      if (strcmp ("source", p) == 0
+	  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN))
+	{
+	  /* FIXME: this is ambiguous.  */
+	  kind = OMP_CLAUSE_DEPEND_SOURCE;
+	  break;
+	}
+
+      if (!cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+	break;
       if (strcmp ("in", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_IN;
       else if (strcmp ("inout", p) == 0)
@@ -33748,24 +33786,16 @@  cp_parser_omp_clause_depend (cp_parser *
 	kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
       else if (strcmp ("out", p) == 0)
 	kind = OMP_CLAUSE_DEPEND_OUT;
-      else if (strcmp ("source", p) == 0)
-	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;
     }
   while (1);
 
-  cp_lexer_consume_token (parser->lexer);
+  if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED)
+    cp_lexer_consume_token (parser->lexer);
 
   if (iterators
       && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
@@ -33789,7 +33819,8 @@  cp_parser_omp_clause_depend (cp_parser *
       return c;
     }
 
-  if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+  if (kind != OMP_CLAUSE_DEPEND_UNSPECIFIED
+      && !cp_parser_require (parser, CPP_COLON, RT_COLON))
     goto resync_fail;
 
   if (kind == OMP_CLAUSE_DEPEND_SINK)
@@ -35253,6 +35284,106 @@  cp_parser_omp_critical (cp_parser *parse
   return c_finish_omp_critical (input_location, stmt, name, clauses);
 }
 
+/* OpenMP 5.0:
+   # pragma omp depobj ( depobj ) depobj-clause new-line
+
+   depobj-clause:
+     depend (dependence-type : locator)
+     destroy
+     update (dependence-type)
+
+   dependence-type:
+     in
+     out
+     inout
+     mutexinout  */
+
+static void
+cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
+{
+  location_t loc = pragma_tok->location;
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    {
+      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+      return;
+    }
+
+  tree depobj = cp_parser_assignment_expression (parser);
+
+  if (!parens.require_close (parser))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+					   /*or_comma=*/false,
+					   /*consume_paren=*/true);
+
+  tree clause = NULL_TREE;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_UNSPECIFIED;
+  location_t c_loc = cp_lexer_peek_token (parser->lexer)->location;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      cp_lexer_consume_token (parser->lexer);
+      if (!strcmp ("depend", p))
+	{
+	  clause = cp_parser_omp_clause_depend (parser, NULL_TREE, c_loc);
+	  if (clause)
+	    clause = finish_omp_clauses (clause, C_ORT_OMP);
+	  if (!clause)
+	    clause = error_mark_node;
+	}
+      else if (!strcmp ("destroy", p))
+	kind = OMP_CLAUSE_DEPEND_LAST;
+      else if (!strcmp ("update", p))
+	{
+	  matching_parens c_parens;
+	  if (c_parens.require_open (parser))
+	    {
+	      location_t c2_loc
+		= cp_lexer_peek_token (parser->lexer)->location;
+	      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+		{
+		  tree id2 = cp_lexer_peek_token (parser->lexer)->u.value;
+		  const char *p2 = IDENTIFIER_POINTER (id2);
+
+		  cp_lexer_consume_token (parser->lexer);
+		  if (!strcmp ("in", p2))
+		    kind = OMP_CLAUSE_DEPEND_IN;
+		  else if (!strcmp ("out", p2))
+		    kind = OMP_CLAUSE_DEPEND_OUT;
+		  else if (!strcmp ("inout", p2))
+		    kind = OMP_CLAUSE_DEPEND_INOUT;
+		  else if (!strcmp ("mutexinoutset", p2))
+		    kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+		}
+	      if (kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+		{
+		  clause = error_mark_node;
+		  error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
+				    "%<mutexinoutset%>");
+		}
+	      if (!c_parens.require_close (parser))
+		cp_parser_skip_to_closing_parenthesis (parser,
+						       /*recovering=*/true,
+						       /*or_comma=*/false,
+						       /*consume_paren=*/true);
+	    }
+	  else
+	    clause = error_mark_node;
+	}
+    }
+  if (!clause && kind == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+    {
+      clause = error_mark_node;
+      error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
+    }
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+
 /* OpenMP 2.5:
    # pragma omp flush flush-vars[opt] new-line
 
@@ -39499,6 +39630,21 @@  cp_parser_pragma (cp_parser *parser, enu
 	  break;
 	default:
 	  goto bad_stmt;
+	}
+      break;
+
+    case PRAGMA_OMP_DEPOBJ:
+      switch (context)
+	{
+	case pragma_compound:
+	  cp_parser_omp_depobj (parser, pragma_tok);
+	  return false;
+	case pragma_stmt:
+	  error_at (pragma_tok->location, "%<#pragma %s%> may only be "
+		    "used in compound statements", "omp depobj");
+	  break;
+	default:
+	  goto bad_stmt;
 	}
       break;
 
--- gcc/cp/cp-tree.h.jj	2018-06-19 10:42:21.292381953 +0200
+++ gcc/cp/cp-tree.h	2018-06-27 18:34:55.947148174 +0200
@@ -4953,6 +4953,13 @@  more_aggr_init_expr_args_p (const aggr_i
 #define ALIGNOF_EXPR_STD_P(NODE) \
   TREE_LANG_FLAG_0 (ALIGNOF_EXPR_CHECK (NODE))
 
+/* OMP_DEPOBJ accessors. These give access to the depobj expression of the
+   #pragma omp depobj directive and the clauses, respectively.  If
+   OMP_DEPOBJ_CLAUSES is INTEGER_CST, it is instead the update clause kind
+   or OMP_CLAUSE_DEPEND_LAST for destroy clause.  */
+#define OMP_DEPOBJ_DEPOBJ(NODE)	 TREE_OPERAND (OMP_DEPOBJ_CHECK (NODE), 0)
+#define OMP_DEPOBJ_CLAUSES(NODE) TREE_OPERAND (OMP_DEPOBJ_CHECK (NODE), 1)
+
 /* An enumeration of the kind of tags that C++ accepts.  */
 enum tag_types {
   none_type = 0, /* Not a tag type.  */
@@ -6968,6 +6975,9 @@  extern void finish_omp_atomic			(enum tr
 						 tree, tree, tree, tree, tree,
 						 tree, enum omp_memory_order);
 extern void finish_omp_barrier			(void);
+extern void finish_omp_depobj			(location_t, tree,
+						 enum omp_clause_depend_kind,
+						 tree);
 extern void finish_omp_flush			(int);
 extern void finish_omp_taskwait			(void);
 extern void finish_omp_taskyield		(void);
--- gcc/cp/cp-tree.def.jj	2018-04-30 14:08:47.954326097 +0200
+++ gcc/cp/cp-tree.def	2018-06-27 18:17:40.422318868 +0200
@@ -498,6 +498,11 @@  DEFTREECODE (BASES, "bases", tcc_type, 0
    instantiation time.  */
 DEFTREECODE (TEMPLATE_INFO, "template_info", tcc_exceptional, 0)
 
+/* OpenMP - #pragma omp depobj
+   Operand 0: OMP_DEPOBJ_DEPOBJ: Depobj expression
+   Operand 1: OMP_DEPOBJ_CLAUSES: List of clauses.  */
+DEFTREECODE (OMP_DEPOBJ, "omp_depobj", tcc_statement, 2)
+
 /* Extensions for Concepts. */
 
 /* Used to represent information associated with constrained declarations. */
--- gcc/cp/semantics.c.jj	2018-06-19 10:42:21.297381958 +0200
+++ gcc/cp/semantics.c	2018-06-28 14:03:15.283848339 +0200
@@ -6837,6 +6837,14 @@  finish_omp_clauses (tree clauses, enum c
 	    {
 	      if (handle_omp_array_sections (c, ort))
 		remove = true;
+	      else if (OMP_CLAUSE_DEPEND_KIND (c)
+		       == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+		{
+		  error_at (OMP_CLAUSE_LOCATION (c),
+			    "%<depend%> clause without dependence type "
+			    "on array section");
+		  remove = true;
+		}
 	      break;
 	    }
 	  if (t == error_mark_node)
@@ -6862,8 +6870,55 @@  finish_omp_clauses (tree clauses, enum c
 			  "in %<depend%> clause", t);
 	      remove = true;
 	    }
-	  else if (!cxx_mark_addressable (t))
-	    remove = true;
+	  else if (TREE_CODE (t) == COMPONENT_REF
+		   && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
+		   && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
+	    {
+	      error_at (OMP_CLAUSE_LOCATION (c),
+			"bit-field %qE in %qs clause", t, "depend");
+	      remove = true;
+	    }
+	  else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_UNSPECIFIED)
+	    {
+	      if (!c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+				     ? TREE_TYPE (TREE_TYPE (t))
+				     : TREE_TYPE (t)))
+		{
+		  error_at (OMP_CLAUSE_LOCATION (c),
+			    "%qE does not have %<omp_depend_t%> type in "
+			    "%<depend%> clause without dependence type", t);
+		  remove = true;
+		}
+	    }
+	  else if (c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+				     ? TREE_TYPE (TREE_TYPE (t))
+				     : TREE_TYPE (t)))
+	    {
+	      error_at (OMP_CLAUSE_LOCATION (c),
+			"%qE should not have %<omp_depend_t%> type in "
+			"%<depend%> clause with dependence type", t);
+	      remove = true;
+	    }
+	  if (!remove)
+	    {
+	      tree addr = cp_build_addr_expr (t, tf_warning_or_error);
+	      if (addr == error_mark_node)
+		remove = true;
+	      else
+		{
+		  t = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+					     tf_warning_or_error);
+		  if (t == error_mark_node)
+		    remove = true;
+		  else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+			   && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+			   && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+			       == TREE_VEC))
+		    TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+		  else
+		    OMP_CLAUSE_DECL (c) = t;
+		}
+	    }
 	  break;
 
 	case OMP_CLAUSE_MAP:
@@ -8755,6 +8810,41 @@  finish_omp_barrier (void)
 }
 
 void
+finish_omp_depobj (location_t loc, tree depobj,
+		   enum omp_clause_depend_kind kind, tree clause)
+{
+  if (!error_operand_p (depobj) && !type_dependent_expression_p (depobj))
+    {
+      if (!lvalue_p (depobj))
+	{
+	  error_at (EXPR_LOC_OR_LOC (depobj, loc),
+		    "%<depobj%> expression is not lvalue expression");
+	  depobj = error_mark_node;
+	}
+    }
+
+  if (processing_template_decl)
+    {
+      if (clause == NULL_TREE)
+	clause = build_int_cst (integer_type_node, kind);
+      add_stmt (build_min_nt_loc (loc, OMP_DEPOBJ, depobj, clause));
+      return;
+    }
+
+  if (!error_operand_p (depobj))
+    {
+      tree addr = cp_build_addr_expr (depobj, tf_warning_or_error);
+      if (addr == error_mark_node)
+	depobj = error_mark_node;
+      else
+	depobj = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+					tf_warning_or_error);
+    }
+
+  c_finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+void
 finish_omp_flush (int mo)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
--- gcc/cp/pt.c.jj	2018-06-18 19:07:09.152186493 +0200
+++ gcc/cp/pt.c	2018-06-28 14:34:46.605431819 +0200
@@ -17237,6 +17237,32 @@  tsubst_expr (tree t, tree args, tsubst_f
       pop_omp_privatization_clauses (r);
       break;
 
+    case OMP_DEPOBJ:
+      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_UNSPECIFIED;
+	  if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
+	    {
+	      tmp = tsubst_omp_clauses (OMP_DEPOBJ_CLAUSES (t), C_ORT_OMP,
+					args, complain, in_decl);
+	      if (tmp == NULL_TREE)
+		tmp = error_mark_node;
+	    }
+	  else
+	    {
+	      kind = (enum omp_clause_depend_kind)
+		     tree_to_uhwi (OMP_DEPOBJ_CLAUSES (t));
+	      tmp = NULL_TREE;
+	    }
+	  finish_omp_depobj (EXPR_LOCATION (t), r, kind, tmp);
+	}
+      else
+	finish_omp_depobj (EXPR_LOCATION (t), r,
+			   OMP_CLAUSE_DEPEND_UNSPECIFIED,
+			   OMP_DEPOBJ_CLAUSES (t));
+      break;
+
     case OACC_DATA:
     case OMP_TARGET_DATA:
     case OMP_TARGET:
--- gcc/cp/cp-objcp-common.c.jj	2018-06-04 18:17:55.714534653 +0200
+++ gcc/cp/cp-objcp-common.c	2018-06-27 18:22:48.515565607 +0200
@@ -446,6 +446,7 @@  cp_common_init_ts (void)
   MARK_TS_TYPED (UNARY_RIGHT_FOLD_EXPR);
   MARK_TS_TYPED (BINARY_LEFT_FOLD_EXPR);
   MARK_TS_TYPED (BINARY_RIGHT_FOLD_EXPR);
+  MARK_TS_TYPED (OMP_DEPOBJ);
 }
 
 #include "gt-cp-cp-objcp-common.h"
--- gcc/cp/constexpr.c.jj	2018-06-04 18:17:50.495526420 +0200
+++ gcc/cp/constexpr.c	2018-06-27 18:43:59.314583341 +0200
@@ -5730,6 +5730,7 @@  potential_constant_expression_1 (tree t,
     case OMP_ATOMIC_READ:
     case OMP_ATOMIC_CAPTURE_OLD:
     case OMP_ATOMIC_CAPTURE_NEW:
+    case OMP_DEPOBJ:
     case OACC_PARALLEL:
     case OACC_KERNELS:
     case OACC_DATA:
--- gcc/cp/lex.c.jj	2018-04-30 14:08:50.527332447 +0200
+++ gcc/cp/lex.c	2018-06-27 19:00:21.374380858 +0200
@@ -289,7 +289,7 @@  cxx_init (void)
    IF_STMT,		CLEANUP_STMT,	FOR_STMT,
    RANGE_FOR_STMT,	WHILE_STMT,	DO_STMT,
    BREAK_STMT,		CONTINUE_STMT,	SWITCH_STMT,
-   EXPR_STMT
+   EXPR_STMT,		OMP_DEPOBJ
   };
 
   memset (&statement_code_p, 0, sizeof (statement_code_p));
--- gcc/cp/dump.c.jj	2018-04-30 14:08:49.863330809 +0200
+++ gcc/cp/dump.c	2018-06-27 18:59:46.905352523 +0200
@@ -327,6 +327,12 @@  cp_dump_tree (void* dump_info, tree t)
       dump_child ("expr", EXPR_STMT_EXPR (t));
       break;
 
+    case OMP_DEPOBJ:
+      dump_stmt (di, t);
+      dump_child ("depobj", OMP_DEPOBJ_DEPOBJ (t));
+      dump_child ("clauses", OMP_DEPOBJ_CLAUSES (t));
+      break;
+
     default:
       break;
     }
--- gcc/cp/cxx-pretty-print.c.jj	2018-06-04 18:17:52.265529212 +0200
+++ gcc/cp/cxx-pretty-print.c	2018-06-28 11:06:51.810642952 +0200
@@ -2068,6 +2068,42 @@  cxx_pretty_printer::statement (tree t)
       declaration (t);
       break;
 
+    case OMP_DEPOBJ:
+      pp_cxx_ws_string (this, "#pragma omp depobj");
+      pp_space (this);
+      pp_cxx_left_paren (this);
+      expression (OMP_DEPOBJ_DEPOBJ (t));
+      pp_cxx_right_paren (this);
+      if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node)
+	{
+	  if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
+	    dump_omp_clauses (this, OMP_DEPOBJ_CLAUSES (t),
+			      pp_indentation (this), 0);
+	  else
+	    switch (tree_to_uhwi (OMP_DEPOBJ_CLAUSES (t)))
+	      {
+	      case OMP_CLAUSE_DEPEND_IN:
+		pp_cxx_ws_string (this, " update(in)");
+		break;
+	      case OMP_CLAUSE_DEPEND_INOUT:
+		pp_cxx_ws_string (this, " update(inout)");
+		break;
+	      case OMP_CLAUSE_DEPEND_OUT:
+		pp_cxx_ws_string (this, " update(out)");
+		break;
+	      case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+		pp_cxx_ws_string (this, " update(mutexinoutset)");
+		break;
+	      case OMP_CLAUSE_DEPEND_LAST:
+		pp_cxx_ws_string (this, " destroy");
+		break;
+	      default:
+		break;
+	      }
+	}
+      pp_needs_newline (this) = true;
+      break;
+
     default:
       c_pretty_printer::statement (t);
       break;
--- gcc/testsuite/c-c++-common/gomp/depend-6.c.jj	2017-05-09 14:13:58.002191451 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-6.c	2018-06-28 13:15:15.441402972 +0200
@@ -3,10 +3,12 @@ 
 
 struct T { int c[3]; };
 struct S { int a; struct T *b; struct T g; };
+struct U { int a : 5; };
 struct S d[10];
 struct S *e[10];
 struct S *f;
 struct S h;
+struct U i;
 
 void
 foo (void)
@@ -29,4 +31,6 @@  foo (void)
   ;
   #pragma omp task depend(inout: h.g.c[2:1])	/* { dg-error "expected" } */
   ;
+  #pragma omp task depend(in: i.a)		/* { dg-error "bit-field '\[^\n\r]*' in 'depend' clause" } */
+  ;
 }
--- gcc/testsuite/c-c++-common/gomp/depend-iterator-2.c.jj	2018-06-13 18:27:33.876741370 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-iterator-2.c	2018-06-28 13:07:08.721033484 +0200
@@ -7,7 +7,7 @@  int *h;
 void
 f1 (void)
 {
-  #pragma omp task depend (iterator : in : a)	/* { dg-error "expected" } */
+  #pragma omp task depend (iterator : in : a)	/* { dg-error "expected|invalid depend kind" } */
   ;
   #pragma omp task depend (iterator (for = 0 : 2) : in : a)	/* { dg-error "expected" } */
   ;
@@ -25,9 +25,7 @@  f1 (void)
   ;
   #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:1), iterator (j = 0:1) : in : a)	/* { dg-error "expected ':'|invalid depend kind|'iterator' undeclared|was not declared|expected '\\)' before ':' token" } */
   ;
   #pragma omp task depend (iterator (i = 0:32) : in : b[i*2:2])
   ;
@@ -89,3 +87,10 @@  f2 (void)
       #pragma omp ordered depend (iterator (int l = 0:2:3) : source)		/* { dg-error "'iterator' modifier incompatible with 'source'" } */
       }
 }
+
+void
+f3 (void)
+{
+  #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a)	/* { dg-error "invalid depend kind|'iterator' undeclared|was not declared|expected '\\)' before ':' token" } */
+  ;
+}
--- gcc/testsuite/c-c++-common/gomp/depobj-1.c.jj	2018-06-27 14:19:59.064026856 +0200
+++ gcc/testsuite/c-c++-common/gomp/depobj-1.c	2018-06-27 14:29:06.171462353 +0200
@@ -0,0 +1,62 @@ 
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+  char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+omp_depend_t bar (void);
+extern const omp_depend_t cdepobj;
+extern omp_depend_t depobj;
+extern omp_depend_t depobja[4];
+extern omp_depend_t *pdepobj;
+int a, b, i, j;
+
+void
+f1 (void)
+{
+  #pragma omp depobj(depobj) depend(in : a)
+  #pragma omp depobj(depobj) update(inout)
+  #pragma omp task depend (depobj)
+  ;
+  #pragma omp depobj(depobj) destroy
+  #pragma omp task depend (iterator (i=1:3) : *(depobja + i))
+  ;
+  #pragma omp depobj(pdepobj[0]) depend(mutexinoutset:a)
+  #pragma omp depobj(*pdepobj) destroy
+}
+
+void
+f2 (void)
+{
+  omp_depend_t depobjb[4];
+  #pragma omp depobj					/* { dg-error "expected" } */
+  #pragma omp depobj destroy				/* { dg-error "expected" } */
+  #pragma omp depobj (depobj)				/* { dg-error "expected 'depend', 'destroy' or 'update' clause" } */
+  #pragma omp depobj (depobj) foobar			/* { dg-error "expected 'depend', 'destroy' or 'update' clause" } */
+  #pragma omp depobj(bar ()) update(inout)		/* { dg-error "'depobj' expression is not lvalue expression" } */
+  #pragma omp depobj (cdepobj) update(in)		/* { dg-error "'const' qualified 'depobj' expression" } */
+  #pragma omp depobj (depobjb) depend(in: a)		/* { dg-error "type of 'depobj' expression is not 'omp_depend_t'" } */
+  #pragma omp depobj (pdepobj) depend(in: a)		/* { dg-error "type of 'depobj' expression is not 'omp_depend_t'" } */
+  #pragma omp depobj (a) destroy			/* { dg-error "type of 'depobj' expression is not 'omp_depend_t'" } */
+  #pragma omp depobj (depobj) depend(a)			/* { dg-error "does not have 'omp_depend_t' type in 'depend' clause without dependence type" } */
+  #pragma omp depobj (depobj) update(foobar)		/* { dg-error "expected 'in', 'out', 'inout' or 'mutexinoutset'" } */
+  #pragma omp depobj (depobj) depend(in: *depobja)	/* { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" } */
+  #pragma omp depobj (depobj) depend(in: a) depend(in: b)	/* { dg-error "expected" } */
+  #pragma omp depobj (depobj) depend(in: a) update(out)	/* { dg-error "expected" } */
+  #pragma omp depobj (depobj) depend(in: a, b)		/* { dg-error "more than one locator in 'depend' clause on 'depobj' construct" } */
+  #pragma omp depobj (depobj) depend(source)		/* { dg-error "'depend\\(source\\)' is only allowed in 'omp ordered'" } */
+  #pragma omp depobj (depobj) depend(sink: i + 1, j - 1)	/* { dg-error "'depend\\(sink\\)' is only allowed in 'omp ordered'" } */
+  #pragma omp depobj (depobj) depend(iterator (i = 0:2) : in : a)	/* { dg-error "'iterator' modifier may not be specified on 'depobj' construct" } */
+  if (0)
+    #pragma omp depobj (depobj) destroy			/* { dg-error "'#pragma omp depobj' may only be used in compound statements" } */
+    ;
+}
+
+void
+f3 (void)
+{
+  #pragma omp task depend (depobja[1:2])		/* { dg-error "'depend' clause without dependence type on array section" } */
+  ;
+  #pragma omp task depend (a)				/* { dg-error "'a' does not have 'omp_depend_t' type in 'depend' clause without dependence type" } */
+  ;
+  #pragma omp task depend (in: depobj)			/* { dg-error "'depobj' should not have 'omp_depend_t' type in 'depend' clause with dependence type" } */
+  ;
+}
--- gcc/testsuite/g++.dg/gomp/depend-iterator-2.C.jj	2018-06-13 19:15:06.993378812 +0200
+++ gcc/testsuite/g++.dg/gomp/depend-iterator-2.C	2018-06-28 13:09:34.557143914 +0200
@@ -8,7 +8,7 @@  template <typename U, typename V, typena
 void
 f1 ()
 {
-  #pragma omp task depend (iterator : in : a)	// { dg-error "expected" }
+  #pragma omp task depend (iterator : in : a)	// { dg-error "expected|invalid depend kind" }
   ;
   #pragma omp task depend (iterator (for = 0 : 2) : in : a)	// { dg-error "expected" }
   ;
@@ -26,9 +26,7 @@  f1 ()
   ;
   #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 = 0:1), iterator (j = 0:1) : in : a)	// { dg-error "expected ':'|invalid depend kind|was not declared|expected '\\)' before ':' token" }
   ;
   #pragma omp task depend (iterator (i = N:32) : in : b[i*2:2])
   ;
@@ -101,10 +99,19 @@  f3 ()
   ;
 }
 
+template <int N>
 void
 f4 ()
 {
+  #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a)	// { dg-error "invalid depend kind|was not declared|expected '\\)' before ':' token" }
+  ;
+}
+
+void
+f5 ()
+{
   f1 <struct S, float, int, 0> ();
   f2 <int, 1> ();
   f3 <struct S, float, int, 0, const int, const long long unsigned> ();
+  f4 <0> ();
 }
--- gcc/testsuite/g++.dg/gomp/depobj-1.C.jj	2018-06-28 13:19:23.842611524 +0200
+++ gcc/testsuite/g++.dg/gomp/depobj-1.C	2018-06-28 14:43:21.164853650 +0200
@@ -0,0 +1,117 @@ 
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+  char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+omp_depend_t bar (void);
+extern const omp_depend_t cdepobj;
+extern omp_depend_t depobj, depobj4;
+extern omp_depend_t depobja[4];
+extern omp_depend_t *pdepobj;
+int a, b, i, j;
+
+template <int N>
+void
+f1 (bool x)
+{
+  #pragma omp depobj(x ? depobj : depobj4) depend(in : x ? a : b)
+  #pragma omp depobj(x ? depobj : depobj4) update(inout)
+  #pragma omp task depend (depobj)
+  ;
+  #pragma omp depobj(depobj) destroy
+  #pragma omp task depend (iterator (i=1:3) : *(depobja + i))
+  ;
+  #pragma omp depobj(pdepobj[0]) depend(mutexinoutset:a)
+  #pragma omp depobj(*pdepobj) destroy
+}
+
+template <typename T, typename T2>
+void
+f2 (T &depobj2, T2 depobj3, T *pdepobj)
+{
+  T depobj1;
+  T depobja[4];
+  #pragma omp depobj(depobj1) depend(in : --a)
+  #pragma omp depobj(depobj1) update(inout)
+  #pragma omp task depend (depobj1)
+  ;
+  #pragma omp depobj(depobj1) destroy
+  #pragma omp depobj(depobj2) depend(in : a)
+  #pragma omp depobj(depobj2) update(inout)
+  #pragma omp task depend (depobj2)
+  ;
+  #pragma omp depobj(depobj2) destroy
+  #pragma omp depobj(depobj3) depend(in : a)
+  #pragma omp depobj(depobj3) update(inout)
+  #pragma omp task depend (depobj3)
+  ;
+  #pragma omp depobj(depobj3) destroy
+  for (int q = 1; q < 3; q++)
+    {
+      #pragma omp depobj(depobja[q]) depend (in:a)
+    }
+  #pragma omp task depend (iterator (i=1:3) : *(depobja + i))
+  ;
+  for (int q = 1; q < 3; q++)
+    {
+      #pragma omp depobj(depobja[q]) destroy
+    }
+  #pragma omp depobj(pdepobj[0]) depend(mutexinoutset:a)
+  #pragma omp depobj(*pdepobj) destroy
+}
+
+void
+f3 (bool x)
+{
+  omp_depend_t depobjx, depobjy;
+  f1 <0> (x);
+  f2 <omp_depend_t, omp_depend_t &> (depobjx, depobjy, pdepobj);
+}
+
+template <int N>
+void
+f4 (void)
+{
+  omp_depend_t depobjb[4];
+  #pragma omp depobj					// { dg-error "expected" }
+  #pragma omp depobj destroy				// { dg-error "expected" }
+  #pragma omp depobj (depobj)				// { dg-error "expected 'depend', 'destroy' or 'update' clause" }
+  #pragma omp depobj (depobj) foobar			// { dg-error "expected 'depend', 'destroy' or 'update' clause" }
+  #pragma omp depobj(bar ()) update(inout)		// { dg-error "'depobj' expression is not lvalue expression" }
+  #pragma omp depobj (cdepobj) update(in)		// { dg-error "'const' qualified 'depobj' expression" }
+  #pragma omp depobj (depobjb) depend(in: a)		// { dg-error "type of 'depobj' expression is not 'omp_depend_t'" }
+  #pragma omp depobj (pdepobj) depend(in: a)		// { dg-error "type of 'depobj' expression is not 'omp_depend_t'" }
+  #pragma omp depobj (a) destroy			// { dg-error "type of 'depobj' expression is not 'omp_depend_t'" }
+  #pragma omp depobj (depobj) depend(a)			// { dg-error "does not have 'omp_depend_t' type in 'depend' clause without dependence type" }
+  #pragma omp depobj (depobj) update(foobar)		// { dg-error "expected 'in', 'out', 'inout' or 'mutexinoutset'" }
+  #pragma omp depobj (depobj) depend(in: *depobja)	// { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" }
+  #pragma omp depobj (depobj) depend(in: a) depend(in: b)	// { dg-error "expected" }
+  #pragma omp depobj (depobj) depend(in: a) update(out)	// { dg-error "expected" }
+  #pragma omp depobj (depobj) depend(in: a, b)		// { dg-error "more than one locator in 'depend' clause on 'depobj' construct" }
+  #pragma omp depobj (depobj) depend(source)		// { dg-error "'depend\\(source\\)' is only allowed in 'omp ordered'" }
+  #pragma omp depobj (depobj) depend(sink: i + 1, j - 1)	// { dg-error "'depend\\(sink\\)' is only allowed in 'omp ordered'" }
+  #pragma omp depobj (depobj) depend(iterator (i = 0:2) : in : a)	// { dg-error "'iterator' modifier may not be specified on 'depobj' construct" }
+  if (0)
+    #pragma omp depobj (depobj) destroy			// { dg-error "'#pragma omp depobj' may only be used in compound statements" }
+    ;
+}
+
+template <int N>
+void
+f5 (void)
+{
+  #pragma omp task depend (depobja[1:2])		// { dg-error "'depend' clause without dependence type on array section" }
+  ;
+  #pragma omp task depend (a)				// { dg-error "'a' does not have 'omp_depend_t' type in 'depend' clause without dependence type" }
+  ;
+  #pragma omp task depend (in: depobj)			// { dg-error "'depobj' should not have 'omp_depend_t' type in 'depend' clause with dependence type" }
+  ;
+}
+
+void
+f6 (omp_depend_t &x)
+{
+  f4 <0> ();
+  f5 <0> ();
+  #pragma omp depobj (x) depend(in: a)
+  #pragma omp depobj (depobj) depend(in: x)		// { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" }
+}
--- include/gomp-constants.h.jj	2018-04-30 13:44:42.856561908 +0200
+++ include/gomp-constants.h	2018-06-26 11:46:40.877447868 +0200
@@ -251,6 +251,12 @@  enum gomp_map_kind
    at most and shifted by this many bits.  */
 #define GOMP_TARGET_ARG_VALUE_SHIFT		16
 
+/* Dependence types in omp_depend_t objects.  */
+#define GOMP_DEPEND_IN			1
+#define GOMP_DEPEND_OUT			2
+#define GOMP_DEPEND_INOUT		3
+#define GOMP_DEPEND_MUTEXINOUTSET	4
+
 /* HSA specific data structures.  */
 
 /* Identifiers of device-specific target arguments.  */
--- libgomp/omp.h.in.jj	2018-05-21 15:54:08.496902995 +0200
+++ libgomp/omp.h.in	2018-06-26 16:31:52.071327689 +0200
@@ -78,6 +78,11 @@  typedef enum omp_sync_hint_t
 
 typedef omp_sync_hint_t omp_lock_hint_t;
 
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t
+{
+  char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
 #ifdef __cplusplus
 extern "C" {
 # define __GOMP_NOTHROW throw ()
--- libgomp/task.c.jj	2018-06-18 19:02:46.486895948 +0200
+++ libgomp/task.c	2018-06-27 12:00:25.156146666 +0200
@@ -166,21 +166,72 @@  gomp_task_handle_depend (struct gomp_tas
 			 void **depend)
 {
   size_t ndepend = (uintptr_t) depend[0];
-  size_t nout = (uintptr_t) depend[1];
   size_t i;
   hash_entry_type ent;
 
+  if (ndepend)
+    {
+      /* depend[0] is total # */
+      size_t nout = (uintptr_t) depend[1]; /* # of out: and inout: */
+      /* ndepend - nout is # of in: */
+      for (i = 0; i < ndepend; i++)
+	{
+	  task->depend[i].addr = depend[2 + i];
+	  task->depend[i].is_in = i >= nout;
+	}
+    }
+  else
+    {
+      ndepend = (uintptr_t) depend[1]; /* total # */
+      size_t nout = (uintptr_t) depend[2]; /* # of out: and inout: */
+      size_t nmutexinoutset = (uintptr_t) depend[3]; /* # of mutexinoutset: */
+      /* For now we treat mutexinoutset like out, which is compliant, but
+	 inefficient.  */
+      size_t nin = (uintptr_t) depend[4]; /* # of in: */
+      /* ndepend - nout - nmutexinoutset - nin is # of depobjs */
+      size_t normal = nout + nmutexinoutset + nin;
+      size_t n = 0;
+      for (i = normal; i < ndepend; i++)
+	{
+	  void **d = (void **) (uintptr_t) depend[5 + i];
+	  switch ((uintptr_t) d[1])
+	    {
+	    case GOMP_DEPEND_OUT:
+	    case GOMP_DEPEND_INOUT:
+	    case GOMP_DEPEND_MUTEXINOUTSET:
+	      break;
+	    case GOMP_DEPEND_IN:
+	      continue;
+	    default:
+	      gomp_fatal ("unknown omp_depend_t dependence type %d",
+			  (int) (uintptr_t) d[1]);
+	    }
+	  task->depend[n].addr = d[0];
+	  task->depend[n++].is_in = 0;
+	}
+      for (i = 0; i < normal; i++)
+	{
+	  task->depend[n].addr = depend[5 + i];
+	  task->depend[n++].is_in = i >= nout + nmutexinoutset;
+	}
+      for (i = normal; i < ndepend; i++)
+	{
+	  void **d = (void **) (uintptr_t) depend[5 + i];
+	  if ((uintptr_t) d[1] != GOMP_DEPEND_IN)
+	    continue;
+	  task->depend[n].addr = d[0];
+	  task->depend[n++].is_in = 1;
+	}
+    }
   task->depend_count = ndepend;
   task->num_dependees = 0;
   if (parent->depend_hash == NULL)
     parent->depend_hash = htab_create (2 * ndepend > 12 ? 2 * ndepend : 12);
   for (i = 0; i < ndepend; i++)
     {
-      task->depend[i].addr = depend[2 + i];
       task->depend[i].next = NULL;
       task->depend[i].prev = NULL;
       task->depend[i].task = task;
-      task->depend[i].is_in = i >= nout;
       task->depend[i].redundant = false;
       task->depend[i].redundant_out = false;
 
@@ -205,7 +256,7 @@  gomp_task_handle_depend (struct gomp_tas
 	      last = ent;
 
 	      /* depend(in:...) doesn't depend on earlier depend(in:...).  */
-	      if (i >= nout && ent->is_in)
+	      if (task->depend[i].is_in && ent->is_in)
 		continue;
 
 	      if (!ent->is_in)
@@ -280,9 +331,18 @@  gomp_task_handle_depend (struct gomp_tas
    then the task may be executed by any member of the team.
 
    DEPEND is an array containing:
+     if depend[0] is non-zero, then:
 	depend[0]: number of depend elements.
-	depend[1]: number of depend elements of type "out".
-	depend[2..N+1]: address of [1..N]th depend element.  */
+	depend[1]: number of depend elements of type "out/inout".
+	depend[2..N+1]: address of [1..N]th depend element.
+     otherwise, when depend[0] is zero, then:
+	depend[1]: number of depend elements.
+	depend[2]: number of depend elements of type "out/inout".
+	depend[3]: number of depend elements of type "mutexinoutset".
+	depend[4]: number of depend elements of type "in".
+	depend[5..4+depend[2]+depend[3]+depend[4]]: address of depend elements
+	depend[5+depend[2]+depend[3]+depend[4]..4+depend[1]]: address of
+		   omp_depend_t objects.  */
 
 void
 GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
@@ -377,7 +437,7 @@  GOMP_task (void (*fn) (void *), void *da
       size_t depend_size = 0;
 
       if (flags & GOMP_TASK_FLAG_DEPEND)
-	depend_size = ((uintptr_t) depend[0]
+	depend_size = ((uintptr_t) (depend[0] ? depend[0] : depend[1])
 		       * sizeof (struct gomp_task_depend_entry));
       task = gomp_malloc (sizeof (*task) + depend_size
 			  + arg_size + arg_align - 1);
@@ -617,7 +677,7 @@  gomp_create_target_task (struct gomp_dev
 
   if (depend != NULL)
     {
-      depend_cnt = (uintptr_t) depend[0];
+      depend_cnt = (uintptr_t) (depend[0] ? depend[0] : depend[1]);
       depend_size = depend_cnt * sizeof (struct gomp_task_depend_entry);
     }
   if (fn)
@@ -1496,21 +1556,50 @@  gomp_task_maybe_wait_for_dependencies (v
   struct gomp_team *team = thr->ts.team;
   struct gomp_task_depend_entry elem, *ent = NULL;
   struct gomp_taskwait taskwait;
-  size_t ndepend = (uintptr_t) depend[0];
+  size_t orig_ndepend = (uintptr_t) depend[0];
   size_t nout = (uintptr_t) depend[1];
+  size_t ndepend = orig_ndepend;
+  size_t normal = ndepend;
+  size_t n = 2;
   size_t i;
   size_t num_awaited = 0;
   struct gomp_task *child_task = NULL;
   struct gomp_task *to_free = NULL;
   int do_wake = 0;
 
+  if (ndepend == 0)
+    {
+      ndepend = nout;
+      nout = (uintptr_t) depend[2] + (uintptr_t) depend[3];
+      normal = nout + (uintptr_t) depend[4];
+      n = 5;
+    }
   gomp_mutex_lock (&team->task_lock);
   for (i = 0; i < ndepend; i++)
     {
-      elem.addr = depend[i + 2];
+      elem.addr = depend[i + n];
+      elem.is_in = i >= nout;
+      if (__builtin_expect (i >= normal, 0))
+	{
+	  void **d = (void **) elem.addr;
+	  switch ((uintptr_t) d[1])
+	    {
+	    case GOMP_DEPEND_IN:
+	      break;
+	    case GOMP_DEPEND_OUT:
+	    case GOMP_DEPEND_INOUT:
+	    case GOMP_DEPEND_MUTEXINOUTSET:
+	      elem.is_in = 0;
+	      break;
+	    default:
+	      gomp_fatal ("unknown omp_depend_t dependence type %d",
+			  (int) (uintptr_t) d[1]);
+	    }
+	  elem.addr = d[0];
+	}
       ent = htab_find (task->depend_hash, &elem);
       for (; ent; ent = ent->next)
-	if (i >= nout && ent->is_in)
+	if (elem.is_in && ent->is_in)
 	  continue;
 	else
 	  {
--- libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c.jj	2018-06-27 11:50:37.190730353 +0200
+++ libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c	2018-06-27 11:45:24.525508965 +0200
@@ -0,0 +1,63 @@ 
+volatile int v;
+
+__attribute__((noipa)) void
+foo (int *p, int i)
+{
+  #pragma omp task depend (out: p[0])
+  v++;
+  #pragma omp task depend (in: p[0])
+  v++;
+  #pragma omp task depend (inout: p[0])
+  v++;
+  #pragma omp task depend (mutexinoutset: p[0])
+  v++;
+  #pragma omp task depend (out: p[0]) depend (in: p[1])
+  v++;
+  #pragma omp task depend (in: p[0]) depend (inout: p[1])
+  v++;
+  #pragma omp task depend (inout: p[0]) depend (mutexinoutset: p[1])
+  v++;
+  #pragma omp task depend (mutexinoutset: p[0]) depend (out: p[1])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : out : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : in : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : inout : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : mutexinoutset : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : out : p[j]) depend (iterator (j=0:2) : in : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : in : p[j]) depend (iterator (j=0:2) : inout : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : inout : p[j]) depend (iterator (j=0:2) : mutexinoutset : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:2) : mutexinoutset : p[j]) depend (iterator (j=0:2) : out : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : out : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : in : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : inout : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : mutexinoutset : p[j])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : out : p[j]) depend (iterator (j=0:i) : in : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : in : p[j]) depend (iterator (j=0:i) : inout : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : inout : p[j]) depend (iterator (j=0:i) : mutexinoutset : p[j + 2])
+  v++;
+  #pragma omp task depend (iterator (j=0:i) : mutexinoutset : p[j]) depend (iterator (j=0:i) : out : p[j + 2])
+  v++;
+}
+
+int
+main ()
+{
+  int p[4];
+  foo (p, 2);
+  foo (p, -1);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c-c++-common/depobj-1.c.jj	2018-06-27 15:31:43.275513633 +0200
+++ libgomp/testsuite/libgomp.c-c++-common/depobj-1.c	2018-06-27 15:47:09.637231807 +0200
@@ -0,0 +1,99 @@ 
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (void)
+{
+  int x = 1;
+  omp_depend_t d1, d2;
+  #pragma omp depobj (d1) depend(in: x)
+  #pragma omp depobj (d2) depend(in: x)
+  #pragma omp depobj (d2) update(out)
+  #pragma omp parallel
+  #pragma omp single
+  {
+    #pragma omp task shared (x) depend(d2)
+    x = 2;
+    #pragma omp task shared (x) depend(d1)
+    if (x != 2)
+      abort ();
+  }
+  #pragma omp depobj (d2) destroy
+  #pragma omp depobj (d1) destroy
+}
+
+void
+dep2 (void)
+{
+  #pragma omp parallel
+  #pragma omp single
+  {
+    int x = 1;
+    omp_depend_t d1, d2;
+    #pragma omp depobj (d1) depend(out: x)
+    #pragma omp depobj (*&d2) depend (in:x)
+    #pragma omp depobj(d2)update(in)
+    #pragma omp task shared (x) depend(d1)
+    x = 2;
+    #pragma omp task shared (x) depend(d2)
+    if (x != 2)
+      abort ();
+    #pragma omp taskwait
+    #pragma omp depobj(d1)destroy
+    #pragma omp depobj((&d2)[0]) destroy
+  }
+}
+
+void
+dep3 (void)
+{
+  omp_depend_t d[2];
+  #pragma omp parallel
+  {
+    int x = 1;
+    #pragma omp single
+    {
+      #pragma omp depobj(d[0]) depend(out:x)
+      #pragma omp depobj(d[1]) depend(in: x)
+      #pragma omp task shared (x) depend(*d)
+      x = 2;
+      #pragma omp task shared (x) depend(*(d + 1))
+      if (x != 2)
+	abort ();
+    }
+  }
+  #pragma omp depobj(d[0]) destroy
+  #pragma omp depobj(d[1]) destroy
+}
+
+int xx;
+omp_depend_t dd1, dd2;
+
+void
+antidep (void)
+{
+  xx = 1;
+  #pragma omp parallel
+  #pragma omp single
+  {
+    #pragma omp task shared(xx) depend(dd2)
+    if (xx != 1)
+      abort ();
+    #pragma omp task shared(xx) depend(dd1)
+    xx = 2;
+  }
+}
+
+int
+main ()
+{
+  dep ();
+  dep2 ();
+  dep3 ();
+  #pragma omp depobj (dd1) depend (inout: xx)
+  #pragma omp depobj (dd2) depend (in : xx)
+  antidep ();
+  #pragma omp depobj (dd2) destroy
+  #pragma omp depobj (dd1) destroy
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/depend-1.C.jj	2018-06-28 15:25:19.944964463 +0200
+++ libgomp/testsuite/libgomp.c++/depend-1.C	2018-06-28 15:25:14.145959638 +0200
@@ -0,0 +1,31 @@ 
+extern "C" void abort ();
+int a, b, c, d, e;
+
+void
+foo (int &x, bool y)
+{
+  #pragma omp task depend (out: x)
+    a = 1;
+  #pragma omp task depend (out: y ? b : c)
+    (y ? b : c) = 2;
+  #pragma omp task depend (inout: --d)
+    d += 4;
+  #pragma omp task depend (in : a, (y ? b : c), d)
+    e = a + b * 10 + c * 100 + d * 1000;
+}
+
+int
+main ()
+{
+  #pragma omp parallel
+  #pragma omp single
+  foo (a, true);
+  if (e != 1 + 20 + 0 + 3000)
+    abort ();
+  a = b = c = d = e = 0;
+  #pragma omp parallel
+  #pragma omp single
+  foo (a, false);
+  if (e != 1 + 0 + 200 + 3000)
+    abort ();
+}
--- libgomp/testsuite/libgomp.c++/depobj-1.C.jj	2018-06-28 15:29:20.598164497 +0200
+++ libgomp/testsuite/libgomp.c++/depobj-1.C	2018-06-28 15:38:44.035632853 +0200
@@ -0,0 +1,103 @@ 
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (omp_depend_t &d1, omp_depend_t *d2)
+{
+  int x = 1;
+  #pragma omp depobj (d1) depend(in: x)
+  #pragma omp depobj (*d2) depend(in: x)
+
+  #pragma omp depobj (d2[0]) update(out)
+  #pragma omp parallel
+  #pragma omp single
+  {
+    #pragma omp task shared (x) depend(*d2)
+    x = 2;
+    #pragma omp task shared (x) depend(d1)
+    if (x != 2)
+      abort ();
+  }
+  #pragma omp depobj (d2[0]) destroy
+  #pragma omp depobj (d1) destroy
+}
+
+template <typename T>
+void
+dep2 (T &d2)
+{
+  T d1;
+  #pragma omp parallel
+  #pragma omp single
+  {
+    int x = 1;
+    #pragma omp depobj (d1) depend(out: x)
+    #pragma omp depobj (*&d2) depend (in:x)
+    #pragma omp depobj(d2)update(in)
+    #pragma omp task shared (x) depend(d1)
+    x = 2;
+    #pragma omp task shared (x) depend(d2)
+    if (x != 2)
+      abort ();
+    #pragma omp taskwait
+    #pragma omp depobj(d1)destroy
+    #pragma omp depobj((&d2)[0]) destroy
+  }
+}
+
+template <typename T>
+void
+dep3 (void)
+{
+  T d[2];
+  #pragma omp parallel
+  {
+    int x = 1;
+    #pragma omp single
+    {
+      #pragma omp depobj(d[0]) depend(out:x)
+      #pragma omp depobj(d[1]) depend(in: x)
+      #pragma omp task shared (x) depend(*d)
+      x = 2;
+      #pragma omp task shared (x) depend(*(d + 1))
+      if (x != 2)
+	abort ();
+    }
+  }
+  #pragma omp depobj(d[0]) destroy
+  #pragma omp depobj(d[1]) destroy
+}
+
+int xx;
+omp_depend_t dd1, dd2;
+
+template <int N>
+void
+antidep (void)
+{
+  xx = 1;
+  #pragma omp parallel
+  #pragma omp single
+  {
+    #pragma omp task shared(xx) depend(dd2)
+    if (xx != 1)
+      abort ();
+    #pragma omp task shared(xx) depend(dd1)
+    xx = 2;
+  }
+}
+
+int
+main ()
+{
+  omp_depend_t d1, d2, d3;
+  dep (d1, &d2);
+  dep2 <omp_depend_t> (d3);
+  dep3 <omp_depend_t> ();
+  #pragma omp depobj (dd1) depend (inout: xx)
+  #pragma omp depobj (dd2) depend (in : xx)
+  antidep <0> ();
+  #pragma omp depobj (dd2) destroy
+  #pragma omp depobj (dd1) destroy
+  return 0;
+}