]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-core.h (enum omp_clause_depend_kind): Add OMP_CLAUSE_DEPEND_UNSPECIFIED.
authorJakub Jelinek <jakub@redhat.com>
Thu, 28 Jun 2018 18:09:53 +0000 (20:09 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 28 Jun 2018 18:09:53 +0000 (20:09 +0200)
* 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.

From-SVN: r262226

39 files changed:
gcc/ChangeLog.gomp
gcc/c-family/ChangeLog.gomp
gcc/c-family/c-common.h
gcc/c-family/c-omp.c
gcc/c-family/c-pragma.c
gcc/c-family/c-pragma.h
gcc/c/ChangeLog.gomp
gcc/c/c-parser.c
gcc/c/c-typeck.c
gcc/cp/ChangeLog.gomp
gcc/cp/constexpr.c
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/dump.c
gcc/cp/lex.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/gimplify.c
gcc/omp-low.c
gcc/testsuite/ChangeLog.gomp
gcc/testsuite/c-c++-common/gomp/depend-6.c
gcc/testsuite/c-c++-common/gomp/depend-iterator-2.c
gcc/testsuite/c-c++-common/gomp/depobj-1.c [new file with mode: 0644]
gcc/testsuite/g++.dg/gomp/depend-iterator-2.C
gcc/testsuite/g++.dg/gomp/depobj-1.C [new file with mode: 0644]
gcc/tree-core.h
gcc/tree-pretty-print.c
include/ChangeLog.gomp [new file with mode: 0644]
include/gomp-constants.h
libgomp/ChangeLog.gomp
libgomp/omp.h.in
libgomp/task.c
libgomp/testsuite/libgomp.c++/depend-1.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/depobj-1.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c-c++-common/depobj-1.c [new file with mode: 0644]

index bcd69a13924d39ac6eea12886f2a1da2617ab56d..cd9b726b09f5801aef5a0017ef24f4c851439c97 100644 (file)
@@ -1,3 +1,14 @@
+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.
+
 2018-06-19  Jakub Jelinek  <jakub@redhat.com>
 
        * gimple.h (enum gf_mask): Add GF_OMP_TASK_TASKWAIT.
index 8d66698f86538972d5476359c968da5d4c4b581a..f56676492364771e2c1dd93529cfcf9257ee3f39 100644 (file)
@@ -1,3 +1,10 @@
+2018-06-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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.
+
 2018-06-19  Jakub Jelinek  <jakub@redhat.com>
 
        * c-common.h (c_finish_omp_flush): Add MO argument.
index eea93dfd18ef37ad99614acbc3533d1375e357d0..230c0761b6a37f1dd5ad77707b015ce41e13a7f2 100644 (file)
@@ -1149,6 +1149,9 @@ extern void c_finish_omp_barrier (location_t);
 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);
index 5c7fb0dcce22ff5be15f2d09e8508fa4e80ead7b..5fd481968a2a9699a2afe8b35800305ab950795e 100644 (file)
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #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, enum tree_code code,
 }
 
 
+/* 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.  */
index ea48ef2a9edfc83666ed29d41bdb8a881095660b..fe21120df2f456e4ea8ff78e924c28355335ba8e 100644 (file)
@@ -1286,6 +1286,7 @@ static const struct omp_pragma_def omp_pragmas[] = {
   { "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 },
index 0e218c9017c438d2f7a2310c7624908f57ede4a7..03fd81401463ccd62c1809b15390e6748898551c 100644 (file)
@@ -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,
index a87f99d0a0dc3ca956a7f142ba0d1b051fdb1a15..c15f2ab17b3db8874b8d793b7193b6e60684a40c 100644 (file)
@@ -1,3 +1,15 @@
+2018-06-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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.
+
 2018-06-19  Jakub Jelinek  <jakub@redhat.com>
 
        * c-parser.c: Include memmodel.h.
index e9be2f5030c1f18f25f0309f2e462555f9735cd2..643b7e23cc5e5218b9a629c5319c8c6da404e943 100644 (file)
@@ -1446,6 +1446,7 @@ static void c_parser_oacc_update (c_parser *);
 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 pragma_context context, bool *if_p)
       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 *parser, tree list)
   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 *parser, tree list)
        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 *parser, tree list)
       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_parser *parser, bool *if_p)
   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
 
index 4385d70a5d52a8ca254bb88f1505330d36000115..61f57635a8f4a84ead599e41dcd7f6da1442443e 100644 (file)
@@ -13771,6 +13771,14 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            {
              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 c_omp_region_type ort)
                        "%<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:
index 6a6bd25f49fdf972c8adc290edfd5e71a6b3593b..acca0ab492fdf0a79c4cb0dc970ac30b4768d338 100644 (file)
@@ -1,3 +1,27 @@
+2018-06-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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.
+
 2018-06-19  Jakub Jelinek  <jakub@redhat.com>
 
        * cp-tree.h (finish_omp_flush): Add MO argument.
index 944c1cdf11ecf934b40ed7667bac7afaca388f86..555f3b8a472917ffeae6a44883e89fbbe6d169ca 100644 (file)
@@ -5730,6 +5730,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     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:
index eef7ed60519db777dd69571f64ad4e30d50cfec3..584f4284b61f22d5ab305eb5be2f3002a1258e17 100644 (file)
@@ -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"
index 1b0326f4e8134ea0c0f51c8c5cf76bdbbf03eff6..e167688001e2b3de2330fa23d45e60cba33c6bd1 100644 (file)
@@ -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. */
index 11e995fff21d263d5aae3fad7c6d39247b45c726..6dee486f7e13df136801e4b468ebbb5ee80833ab 100644 (file)
@@ -4953,6 +4953,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #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 tree_code, enum tree_code,
                                                 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);
index df81aa37ce89965106407943b15a8f0836edf795..e08d07aa428ea3fbc81d355ce4bdf52e591f45a7 100644 (file)
@@ -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;
index 9c1e5fc781aefb29ccb0c6c698ed2d31e639f9e0..394e6b87cb5672df057ce2e64624216e6003db95 100644 (file)
@@ -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;
     }
index 4d30eb5c85d57cc5c6a370b7024192d2c9b81fbd..fabc5fba2fc35e9d09e1e7d037e056735d2186b6 100644 (file)
@@ -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));
index 01b01475ab48dd9d23988e3bda907ad9d9038a94..681de3cd10ba7a0dd04d5177418370f540166309 100644 (file)
@@ -31619,8 +31619,13 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
          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 *parser)
                                           /*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 *parser, tree list, location_t loc)
   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 *parser, tree list, location_t loc)
        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 *parser, tree list, location_t loc)
       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 *parser, cp_token *pragma_tok, bool *if_p)
   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
 
@@ -39502,6 +39633,21 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
        }
       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;
+
     case PRAGMA_OMP_FLUSH:
       switch (context)
        {
index 49020576f1582ea68f088016e878f1dbd49843f9..7f0d4615a15bd637b39e20770576bac6b2dc32a5 100644 (file)
@@ -17237,6 +17237,32 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       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:
index 6bd1cf05582861d67c8aaf8e288a1206ab766dcb..9aac180b1a8c236b60ad954798d09ffd7eeb18d5 100644 (file)
@@ -6837,6 +6837,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            {
              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_omp_region_type ort)
                          "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:
@@ -8754,6 +8809,41 @@ finish_omp_barrier (void)
   finish_expr_stmt (stmt);
 }
 
+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)
 {
index 56bab57a0eae0551111be80ef64dd5adf32ea18d..64d4abd472a1ad5b10747200778fb931ef12a008 100644 (file)
@@ -7566,10 +7566,11 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
 {
   tree c;
   gimple *g;
-  size_t n[2] = { 0, 0 };
-  tree counts[2] = { NULL_TREE, NULL_TREE };
+  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, gimple_seq *pre_p)
        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, gimple_seq *pre_p)
        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, gimple_seq *pre_p)
       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, gimple_seq *pre_p)
     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, gimple_seq *pre_p)
        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, gimple_seq *pre_p)
       }
   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),
index 70dd6b98ae1762c2d2a7be6cc9d09cf964a57d82..14ce032402c53ee0e0fac21f71a1f88f705d0ca2 100644 (file)
@@ -7351,7 +7351,7 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
 {
   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, gimple_seq *iseq, gimple_seq *oseq)
          /* 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, gimple_seq *iseq, gimple_seq *oseq)
        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++)
     {
-      if ((i ? n_in : n_out) == 0)
+      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 (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);
index 2e2a212644e559cfe10655536b9bbb6a301fbe5a..d6eb862db8050a720c4b46989fbcf7b8d36d10e7 100644 (file)
@@ -1,3 +1,14 @@
+2018-06-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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.
+
 2018-06-19  Jakub Jelinek  <jakub@redhat.com>
 
        * c-c++-common/gomp/flush-1.c: New test.
index 95ec3fdeddeacfce391c04f3a9214823c7cbb342..4684653a06666323577d2b8286e77faa6d8bf2b2 100644 (file)
@@ -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" } */
+  ;
 }
index 94caa5bb06f483f70de0178902bf7bc8bfade0dc..22e3894ce99525872407092193366c317918b0d7 100644 (file)
@@ -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" } */
+  ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/depobj-1.c b/gcc/testsuite/c-c++-common/gomp/depobj-1.c
new file mode 100644 (file)
index 0000000..770f111
--- /dev/null
@@ -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" } */
+  ;
+}
index 347af46344294f7918c61f95cf915cc92dda459a..5189095c916a6be09ff884e858d1e403df9a61fd 100644 (file)
@@ -8,7 +8,7 @@ template <typename U, typename V, typename W, W N>
 void
 f1 ()
 {
-  #pragma omp task depend (iterator : in : a)  // { dg-error "expected" }
+  #pragma omp task depend (iterator : 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> ();
 }
diff --git a/gcc/testsuite/g++.dg/gomp/depobj-1.C b/gcc/testsuite/g++.dg/gomp/depobj-1.C
new file mode 100644 (file)
index 0000000..2b26daa
--- /dev/null
@@ -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" }
+}
index a9107b4fd170efe05d4e1bf044540c47b6c0a700..ec0679938603529a3142168feeb8af18ba8d6c14 100644 (file)
@@ -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,
index c886cb5597a2f7ec1aea22ffd03054dff2fe8f08..8cf42c01c0d6829e97cb4981b56273ea31195e2b 100644 (file)
@@ -674,6 +674,9 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
       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, tree clause, int spc, dump_flags_t flags)
            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);
       }
diff --git a/include/ChangeLog.gomp b/include/ChangeLog.gomp
new file mode 100644 (file)
index 0000000..7536538
--- /dev/null
@@ -0,0 +1,10 @@
+2018-06-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * gomp-constants.h (GOMP_DEPEND_IN, GOMP_DEPEND_OUT,
+       GOMP_DEPEND_INOUT, GOMP_DEPEND_MUTEXINOUTSET): Define.
+\f
+Copyright (C) 2018 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
index ccfb657c735e61d07ebefc1d31170c0cd41806af..325a0e492b69bbfb7150f4e942239d881b494d51 100644 (file)
@@ -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.  */
index 4e3142435bc9ea2053c47edee892536b64f635cf..2bb3f3b102767fedb62744a3f18ef58dac4716d9 100644 (file)
@@ -1,3 +1,18 @@
+2018-06-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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.
+
 2018-06-19  Jakub Jelinek  <jakub@redhat.com>
 
        * libgomp_g.h (GOMP_taskwait_depend): Add prototype.
index 24a19adb4565621504a3166e72349d476360fd82..3d350dd089b09b003aeaa80f7e603fbd1d2103e8 100644 (file)
@@ -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 ()
index d91b0576fbdd5862e1d96cb8ec870a50355606c1..3813a382fc10ff029a6c1bab50021ff4e868022e 100644 (file)
@@ -166,21 +166,72 @@ gomp_task_handle_depend (struct gomp_task *task, struct gomp_task *parent,
                         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_task *task, struct gomp_task *parent,
              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_task *task, struct gomp_task *parent,
    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 *data, void (*cpyfn) (void *, void *),
       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_device_descr *devicep,
 
   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 (void **depend)
   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
          {
diff --git a/libgomp/testsuite/libgomp.c++/depend-1.C b/libgomp/testsuite/libgomp.c++/depend-1.C
new file mode 100644 (file)
index 0000000..71a24d1
--- /dev/null
@@ -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 ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/depobj-1.C b/libgomp/testsuite/libgomp.c++/depobj-1.C
new file mode 100644 (file)
index 0000000..59950d3
--- /dev/null
@@ -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;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c b/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c
new file mode 100644 (file)
index 0000000..fb4e5d8
--- /dev/null
@@ -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;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depobj-1.c b/libgomp/testsuite/libgomp.c-c++-common/depobj-1.c
new file mode 100644 (file)
index 0000000..484a612
--- /dev/null
@@ -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;
+}