Hi!

I've committed following patch to gomp-5_0-branch, which:
1) adds support for memory-order clauses other than seq_cst to atomic
   construct
2) adds support for hint clause on atomic construct, fixes some hint related
   glitches on critical construct; hints are ignored aftere checking their
   arguments
3) adds parsing of the requires directive (though not yet passing that info
   to libgomp to be able to filter out some devices)

Regtested on x86_64-linux.

2018-05-31  Jakub Jelinek  <ja...@redhat.com>

        * Makefile.in (GTFILES): Add omp-general.h.
        * gengtype.c (open_base_files): Likewise.
        * tree-core.h (enum omp_memory_order): New enum.
        (struct tree_base): Add omp_atomic_memory_order field into union.
        Remove OMP_ATOMIC_SEQ_CST comment.
        * tree.h (OMP_ATOMIC_SEQ_CST): Remove.
        (OMP_ATOMIC_MEMORY_ORDER): Define.
        * tree-pretty-print.h (dump_omp_atomic_memory_order): Declare.
        * tree-pretty-print.c (dump_omp_atomic_memory_order): New function.
        (dump_generic_node): Use it.
        * gimple.h (enum gf_mask): Remove GF_OMP_ATOMIC_SEQ_CST, add
        GF_OMP_ATOMIC_MEMORY_ORDER, use different value for
        GF_OMP_ATOMIC_NEED_VALUE.
        (gimple_build_omp_atomic_load): Add enum omp_memory_order argument.
        (gimple_build_omp_atomic_store): Likewise.
        (gimple_omp_atomic_seq_cst_p): Remove.
        (gimple_omp_atomic_memory_order): New function.
        (gimple_omp_atomic_set_seq_cst): Remove.
        (gimple_omp_atomic_set_memory_order): New function.
        * gimple.c (gimple_build_omp_atomic_load): Add mo argument, call
        gimple_omp_atomic_set_memory_order.
        (gimple_build_omp_atomic_store): Likewise.
        * gimple-pretty-print.c (dump_gimple_omp_atomic_load,
        dump_gimple_omp_atomic_store): Use dump_omp_atomic_memory_order.
        * gimplify.c (gimplify_omp_atomic): Use OMP_ATOMIC_MEMORY_ORDER instead
        of OMP_ATOMIC_SEQ_CST, pass it as new argument to
        gimple_build_omp_atomic_load and gimple_build_omp_atomic_store, remove
        gimple_omp_atomic_set_seq_cst calls.
        * omp-general.h (enum omp_requires): New enum.
        (omp_requires_mask): Declare.
        * omp-general.c (enum omp_requires): New variable.
        * omp-expand.c (omp_memory_order_to_memmodel): New function.
        (expand_omp_atomic_load, expand_omp_atomic_store,
        expand_omp_atomic_fetch_op): Use it and gimple_omp_atomic_memory_order
        instead of gimple_omp_atomic_seq_cst_p.
        * omp-low.c (lower_reduction_clauses): Initialize
        OMP_ATOMIC_MEMORY_ORDER to relaxed.
        * tree-parloops.c (create_call_for_reduction_1): Pass
        OMP_MEMORY_ORDER_RELAXED as new argument to dump_gimple_omp_atomic_load
        and dump_gimple_omp_atomic_store.
c-family/
        * c-common.h (c_finish_omp_atomic): Replace bool seq_cst argument with
        enum omp_memory_order memory_order.
        * c-omp.c (c_finish_omp_atomic): Likewise.  Set OMP_ATOMIC_MEMORY_ORDER
        instead of OMP_ATOMIC_SEQ_CST.
        * c-pragma.c (omp_pragmas): Add requires.
        * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_REQUIRES.
c/
        * c-parser.c (c_parser_omp_requires): New function.
        (c_parser_pragma): Handle PRAGMA_OMP_REQUIRES.
        (c_parser_omp_clause_hint): Require constant integer expression rather
        than just integer expression.
        (c_parser_omp_atomic): Parse hint and memory order clauses.  Handle
        default memory order from requires directive if any.  Adjust
        c_finish_omp_atomic caller.
        (c_parser_omp_critical): Allow comma in between (name) and hint clause.
        (c_parser_omp_target): Set OMP_REQUIRES_TARGET_USED bit in
        omp_requires_mask.
cp/
        * cp-tree.h (OMP_ATOMIC_DEPENDENT_P): Return true also for first
        argument being OMP_CLAUSE.
        (finish_omp_atomic): Remove seq_cst argument.  Add clauses and mo
        arguments.
        * parser.c (cp_parser_omp_atomic): Parse hint and memory order clauses.
        Handle default memory order from requires directive if any.  Adjust
        finish_omp_atomic caller.
        (cp_parser_omp_critical): Allow comma in between (name) and hint
        clause.
        (cp_parser_omp_target): Set OMP_REQUIRES_TARGET_USED bit in
        omp_requires_mask.
        (cp_parser_omp_requires): New function.
        (cp_parser_pragma): Handle PRAGMA_OMP_REQUIRES.
        * pt.c (tsubst_expr) <case OMP_ATOMIC>: Call tsubst_omp_clauses
        on clauses if any, adjust finish_omp_atomic caller.  Use
        OMP_ATOMIC_MEMORY_ORDER rather than OMP_ATOMIC_SEQ_CST.
        * semantics.c (finish_omp_clauses): Use error_at rather than
        error for priority and hint clause diagnostics.  Fix pasto for
        hint clause.  Diagnose hint expression that doesn't fold into
        INTEGER_CST.
        (finish_omp_atomic): Remove seq_cst argument.  Add clauses and mo
        arguments.  Adjust c_finish_omp_atomic caller.  Stick clauses if
        any into first argument of wrapping OMP_ATOMIC.
fortran/
        * trans-openmp.c (gfc_trans_omp_atomic): Set OMP_ATOMIC_MEMORY_ORDER
        rather than OMP_ATOMIC_SEQ_CST.
testsuite/
        * c-c++-common/gomp/atomic-17.c: New test.
        * c-c++-common/gomp/atomic-18.c: New test.
        * c-c++-common/gomp/atomic-19.c: New test.
        * c-c++-common/gomp/atomic-20.c: New test.
        * c-c++-common/gomp/atomic-21.c: New test.
        * c-c++-common/gomp/atomic-22.c: New test.
        * c-c++-common/gomp/critical-1.c: New test.
        * c-c++-common/gomp/critical-2.c: New test.
        * c-c++-common/gomp/requires-1.c: New test.
        * c-c++-common/gomp/requires-2.c: New test.
        * c-c++-common/gomp/requires-3.c: New test.
        * c-c++-common/gomp/requires-4.c: New test.
        * gcc.dg/gomp/atomic-5.c (f1): Add another expected error.
        * g++.dg/gomp/atomic-18.C: New test.
        * g++.dg/gomp/atomic-19.C: New test.
        * g++.dg/gomp/atomic-5.C (f1): Add another expected error.
        * g++.dg/gomp/critical-3.C: New test.

--- gcc/Makefile.in.jj  2018-04-30 14:21:15.626026945 +0200
+++ gcc/Makefile.in     2018-05-25 13:22:07.340534680 +0200
@@ -2587,6 +2587,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/inp
   $(srcdir)/internal-fn.h \
   $(srcdir)/hsa-common.c \
   $(srcdir)/calls.c \
+  $(srcdir)/omp-general.h \
   @all_gtfiles@
 
 # Compute the list of GT header files from the corresponding C sources,
--- gcc/tree-core.h.jj  2018-05-07 14:47:37.710983431 +0200
+++ gcc/tree-core.h     2018-05-25 14:45:28.369929705 +0200
@@ -529,6 +529,17 @@ enum omp_clause_defaultmap_kind {
   OMP_CLAUSE_DEFAULTMAP_MASK = 7 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1)
 };
 
+/* memory-order-clause on OpenMP atomic/flush constructs or
+   argument of atomic_default_mem_order clause.  */
+enum omp_memory_order {
+  OMP_MEMORY_ORDER_UNSPECIFIED,
+  OMP_MEMORY_ORDER_RELAXED,
+  OMP_MEMORY_ORDER_ACQUIRE,
+  OMP_MEMORY_ORDER_RELEASE,
+  OMP_MEMORY_ORDER_ACQ_REL,
+  OMP_MEMORY_ORDER_SEQ_CST
+};
+
 /* There is a TYPE_QUAL value for each type qualifier.  They can be
    combined by bitwise-or to form the complete set of qualifiers for a
    type.  */
@@ -1021,6 +1032,9 @@ struct GTY(()) tree_base {
     /* Internal function code.  */
     enum internal_fn ifn;
 
+    /* OMP_ATOMIC* memory order.  */
+    enum omp_memory_order omp_atomic_memory_order;
+
     /* The following two fields are used for MEM_REF and TARGET_MEM_REF
        expression trees and specify known data non-dependences.  For
        two memory references in a function they are known to not
@@ -1161,9 +1175,6 @@ struct GTY(()) tree_base {
        OMP_PARALLEL_COMBINED in
            OMP_PARALLEL
 
-       OMP_ATOMIC_SEQ_CST in
-          OMP_ATOMIC*
-
        OMP_CLAUSE_PRIVATE_OUTER_REF in
           OMP_CLAUSE_PRIVATE
 
--- gcc/tree.h.jj       2018-05-02 17:51:03.371341293 +0200
+++ gcc/tree.h  2018-05-24 18:16:22.182317205 +0200
@@ -1452,11 +1452,10 @@ extern tree maybe_wrap_with_location (tr
 #define OMP_TARGET_COMBINED(NODE) \
   (OMP_TARGET_CHECK (NODE)->base.private_flag)
 
-/* True if OMP_ATOMIC* is supposed to be sequentially consistent
-   as opposed to relaxed.  */
-#define OMP_ATOMIC_SEQ_CST(NODE) \
+/* Memory order for OMP_ATOMIC*.  */
+#define OMP_ATOMIC_MEMORY_ORDER(NODE) \
   (TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
-                    OMP_ATOMIC_CAPTURE_NEW)->base.private_flag)
+                    OMP_ATOMIC_CAPTURE_NEW)->base.u.omp_atomic_memory_order)
 
 /* True on a PRIVATE clause if its decl is kept around for debugging
    information only and its DECL_VALUE_EXPR is supposed to point
--- gcc/tree-pretty-print.c.jj  2018-05-07 14:48:58.490080754 +0200
+++ gcc/tree-pretty-print.c     2018-05-25 11:48:50.048752998 +0200
@@ -1270,6 +1270,34 @@ dump_block_node (pretty_printer *pp, tre
     }
 }
 
+/* Dump #pragma omp atomic memory order clause.  */
+
+void
+dump_omp_atomic_memory_order (pretty_printer *pp, enum omp_memory_order mo)
+{
+  switch (mo)
+    {
+    case OMP_MEMORY_ORDER_RELAXED:
+      pp_string (pp, " relaxed");
+      break;
+    case OMP_MEMORY_ORDER_SEQ_CST:
+      pp_string (pp, " seq_cst");
+      break;
+    case OMP_MEMORY_ORDER_ACQ_REL:
+      pp_string (pp, " acq_rel");
+      break;
+    case OMP_MEMORY_ORDER_ACQUIRE:
+      pp_string (pp, " acquire");
+      break;
+    case OMP_MEMORY_ORDER_RELEASE:
+      pp_string (pp, " release");
+      break;
+    case OMP_MEMORY_ORDER_UNSPECIFIED:
+      break;
+    default:
+      gcc_unreachable ();
+    }
+}
 
 /* Dump the node NODE on the pretty_printer PP, SPC spaces of
    indent.  FLAGS specifies details to show in the dump (see TDF_* in
@@ -3196,8 +3224,7 @@ dump_generic_node (pretty_printer *pp, t
 
     case OMP_ATOMIC:
       pp_string (pp, "#pragma omp atomic");
-      if (OMP_ATOMIC_SEQ_CST (node))
-       pp_string (pp, " seq_cst");
+      dump_omp_atomic_memory_order (pp, OMP_ATOMIC_MEMORY_ORDER (node));
       newline_and_indent (pp, spc + 2);
       dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
       pp_space (pp);
@@ -3208,8 +3235,7 @@ dump_generic_node (pretty_printer *pp, t
 
     case OMP_ATOMIC_READ:
       pp_string (pp, "#pragma omp atomic read");
-      if (OMP_ATOMIC_SEQ_CST (node))
-       pp_string (pp, " seq_cst");
+      dump_omp_atomic_memory_order (pp, OMP_ATOMIC_MEMORY_ORDER (node));
       newline_and_indent (pp, spc + 2);
       dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
       pp_space (pp);
@@ -3218,8 +3244,7 @@ dump_generic_node (pretty_printer *pp, t
     case OMP_ATOMIC_CAPTURE_OLD:
     case OMP_ATOMIC_CAPTURE_NEW:
       pp_string (pp, "#pragma omp atomic capture");
-      if (OMP_ATOMIC_SEQ_CST (node))
-       pp_string (pp, " seq_cst");
+      dump_omp_atomic_memory_order (pp, OMP_ATOMIC_MEMORY_ORDER (node));
       newline_and_indent (pp, spc + 2);
       dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
       pp_space (pp);
--- gcc/tree-pretty-print.h.jj  2018-04-30 13:49:30.863794828 +0200
+++ gcc/tree-pretty-print.h     2018-05-25 11:49:10.678768655 +0200
@@ -39,6 +39,8 @@ extern void print_generic_stmt (FILE *,
 extern void print_generic_stmt_indented (FILE *, tree, dump_flags_t, int);
 extern void print_generic_expr (FILE *, tree, dump_flags_t = TDF_NONE);
 extern void dump_omp_clauses (pretty_printer *, tree, int, dump_flags_t);
+extern void dump_omp_atomic_memory_order (pretty_printer *,
+                                         enum omp_memory_order);
 extern int dump_generic_node (pretty_printer *, tree, int, dump_flags_t, bool);
 extern void print_declaration (pretty_printer *, tree, int, dump_flags_t);
 extern int op_code_prio (enum tree_code);
--- gcc/gimple.h.jj     2018-04-30 14:21:17.356027663 +0200
+++ gcc/gimple.h        2018-05-31 17:14:16.365473962 +0200
@@ -192,8 +192,8 @@ enum gf_mask {
     GF_OMP_RETURN_NOWAIT       = 1 << 0,
 
     GF_OMP_SECTION_LAST                = 1 << 0,
-    GF_OMP_ATOMIC_NEED_VALUE   = 1 << 0,
-    GF_OMP_ATOMIC_SEQ_CST      = 1 << 1,
+    GF_OMP_ATOMIC_MEMORY_ORDER  = (1 << 3) - 1,
+    GF_OMP_ATOMIC_NEED_VALUE   = 1 << 3,
     GF_PREDICT_TAKEN           = 1 << 15
 };
 
@@ -1474,8 +1474,9 @@ gimple *gimple_build_omp_sections_switch
 gomp_single *gimple_build_omp_single (gimple_seq, tree);
 gomp_target *gimple_build_omp_target (gimple_seq, int, tree);
 gomp_teams *gimple_build_omp_teams (gimple_seq, tree);
-gomp_atomic_load *gimple_build_omp_atomic_load (tree, tree);
-gomp_atomic_store *gimple_build_omp_atomic_store (tree);
+gomp_atomic_load *gimple_build_omp_atomic_load (tree, tree,
+                                               enum omp_memory_order);
+gomp_atomic_store *gimple_build_omp_atomic_store (tree, enum omp_memory_order);
 gtransaction *gimple_build_transaction (gimple_seq);
 extern void gimple_seq_add_stmt (gimple_seq *, gimple *);
 extern void gimple_seq_add_stmt_without_update (gimple_seq *, gimple *);
@@ -2317,26 +2318,27 @@ gimple_omp_atomic_set_need_value (gimple
 }
 
 
-/* Return true if OMP atomic load/store statement G has the
-   GF_OMP_ATOMIC_SEQ_CST flag set.  */
+/* Return the memory order of the OMP atomic load/store statement G.  */
 
-static inline bool
-gimple_omp_atomic_seq_cst_p (const gimple *g)
+static inline enum omp_memory_order
+gimple_omp_atomic_memory_order (const gimple *g)
 {
   if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
     GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  return (gimple_omp_subcode (g) & GF_OMP_ATOMIC_SEQ_CST) != 0;
+  return (enum omp_memory_order)
+        (gimple_omp_subcode (g) & GF_OMP_ATOMIC_MEMORY_ORDER);
 }
 
 
-/* Set the GF_OMP_ATOMIC_SEQ_CST flag on G.  */
+/* Set the memory order on G.  */
 
 static inline void
-gimple_omp_atomic_set_seq_cst (gimple *g)
+gimple_omp_atomic_set_memory_order (gimple *g, enum omp_memory_order mo)
 {
   if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
     GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  g->subcode |= GF_OMP_ATOMIC_SEQ_CST;
+  g->subcode = ((g->subcode & ~GF_OMP_ATOMIC_MEMORY_ORDER)
+               | (mo & GF_OMP_ATOMIC_MEMORY_ORDER));
 }
 
 
--- gcc/gimple.c.jj     2018-04-30 14:21:16.310027225 +0200
+++ gcc/gimple.c        2018-05-31 17:15:01.873546351 +0200
@@ -1188,12 +1188,13 @@ gimple_build_omp_teams (gimple_seq body,
 /* Build a GIMPLE_OMP_ATOMIC_LOAD statement.  */
 
 gomp_atomic_load *
-gimple_build_omp_atomic_load (tree lhs, tree rhs)
+gimple_build_omp_atomic_load (tree lhs, tree rhs, enum omp_memory_order mo)
 {
   gomp_atomic_load *p
     = as_a <gomp_atomic_load *> (gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD, 0));
   gimple_omp_atomic_load_set_lhs (p, lhs);
   gimple_omp_atomic_load_set_rhs (p, rhs);
+  gimple_omp_atomic_set_memory_order (p, mo);
   return p;
 }
 
@@ -1202,11 +1203,12 @@ gimple_build_omp_atomic_load (tree lhs,
    VAL is the value we are storing.  */
 
 gomp_atomic_store *
-gimple_build_omp_atomic_store (tree val)
+gimple_build_omp_atomic_store (tree val, enum omp_memory_order mo)
 {
   gomp_atomic_store *p
     = as_a <gomp_atomic_store *> (gimple_alloc (GIMPLE_OMP_ATOMIC_STORE, 0));
   gimple_omp_atomic_store_set_val (p, val);
+  gimple_omp_atomic_set_memory_order (p, mo);
   return p;
 }
 
--- gcc/gimple-pretty-print.c.jj        2018-04-30 14:19:56.942994630 +0200
+++ gcc/gimple-pretty-print.c   2018-05-25 12:31:11.715831628 +0200
@@ -2403,8 +2403,8 @@ dump_gimple_omp_atomic_load (pretty_prin
   else
     {
       pp_string (buffer, "#pragma omp atomic_load");
-      if (gimple_omp_atomic_seq_cst_p (gs))
-       pp_string (buffer, " seq_cst");
+      dump_omp_atomic_memory_order (buffer,
+                                   gimple_omp_atomic_memory_order (gs));
       if (gimple_omp_atomic_need_value_p (gs))
        pp_string (buffer, " [needed]");
       newline_and_indent (buffer, spc + 2);
@@ -2435,9 +2435,10 @@ dump_gimple_omp_atomic_store (pretty_pri
     }
   else
     {
-      pp_string (buffer, "#pragma omp atomic_store ");
-      if (gimple_omp_atomic_seq_cst_p (gs))
-       pp_string (buffer, "seq_cst ");
+      pp_string (buffer, "#pragma omp atomic_store");
+      dump_omp_atomic_memory_order (buffer,
+                                   gimple_omp_atomic_memory_order (gs));
+      pp_space (buffer);
       if (gimple_omp_atomic_need_value_p (gs))
        pp_string (buffer, "[needed] ");
       pp_left_paren (buffer);
--- gcc/gimplify.c.jj   2018-05-04 19:08:55.309273302 +0200
+++ gcc/gimplify.c      2018-05-31 17:16:02.925643457 +0200
@@ -11152,7 +11152,8 @@ gimplify_omp_atomic (tree *expr_p, gimpl
       != GS_ALL_DONE)
     return GS_ERROR;
 
-  loadstmt = gimple_build_omp_atomic_load (tmp_load, addr);
+  loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
+                                          OMP_ATOMIC_MEMORY_ORDER (*expr_p));
   gimplify_seq_add_stmt (pre_p, loadstmt);
   if (rhs && gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
       != GS_ALL_DONE)
@@ -11160,13 +11161,9 @@ gimplify_omp_atomic (tree *expr_p, gimpl
 
   if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
     rhs = tmp_load;
-  storestmt = gimple_build_omp_atomic_store (rhs);
+  storestmt
+    = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
   gimplify_seq_add_stmt (pre_p, storestmt);
-  if (OMP_ATOMIC_SEQ_CST (*expr_p))
-    {
-      gimple_omp_atomic_set_seq_cst (loadstmt);
-      gimple_omp_atomic_set_seq_cst (storestmt);
-    }
   switch (TREE_CODE (*expr_p))
     {
     case OMP_ATOMIC_READ:
--- gcc/gengtype.c.jj   2018-04-30 13:49:30.698794472 +0200
+++ gcc/gengtype.c      2018-05-25 16:29:13.412013305 +0200
@@ -1724,7 +1724,8 @@ open_base_files (void)
       "tree-dfa.h", "tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
       "except.h", "output.h",  "cfgloop.h", "target.h", "lto-streamer.h",
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
-      "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-offload.h", NULL
+      "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
+      "omp-offload.h", NULL
     };
     const char *const *ifp;
     outf_p gtype_desc_c;
--- gcc/omp-general.h.jj        2018-04-30 14:21:00.219020618 +0200
+++ gcc/omp-general.h   2018-05-25 16:00:06.474394536 +0200
@@ -89,4 +89,16 @@ extern bool offloading_function_p (tree
 extern int oacc_get_fn_dim_size (tree fn, int axis);
 extern int oacc_get_ifn_dim_arg (const gimple *stmt);
 
+enum omp_requires {
+  OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER = 0xf,
+  OMP_REQUIRES_UNIFIED_ADDRESS = 0x10,
+  OMP_REQUIRES_UNIFIED_SHARED_MEMORY = 0x20,
+  OMP_REQUIRES_DYNAMIC_ALLOCATORS = 0x40,
+  OMP_REQUIRES_REVERSE_OFFLOAD = 0x80,
+  OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED = 0x100,
+  OMP_REQUIRES_TARGET_USED = 0x200
+};
+
+extern GTY(()) enum omp_requires omp_requires_mask;
+
 #endif /* GCC_OMP_GENERAL_H */
--- gcc/omp-general.c.jj        2018-04-30 15:57:22.387472657 +0200
+++ gcc/omp-general.c   2018-05-25 13:20:34.935455598 +0200
@@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.
 #include "stringpool.h"
 #include "attribs.h"
 
+enum omp_requires omp_requires_mask;
+
 tree
 omp_find_clause (tree clauses, enum omp_clause_code kind)
 {
--- gcc/omp-expand.c.jj 2018-04-30 14:08:55.188343950 +0200
+++ gcc/omp-expand.c    2018-05-25 18:14:54.431217055 +0200
@@ -6016,6 +6016,24 @@ expand_omp_synch (struct omp_region *reg
     }
 }
 
+/* Translate enum omp_memory_order to enum memmodel.  The two enums
+   are using different numbers so that OMP_MEMORY_ORDER_UNSPECIFIED
+   is 0.  */
+
+static enum memmodel
+omp_memory_order_to_memmodel (enum omp_memory_order mo)
+{
+  switch (mo)
+    {
+    case OMP_MEMORY_ORDER_RELAXED: return MEMMODEL_RELAXED;
+    case OMP_MEMORY_ORDER_ACQUIRE: return MEMMODEL_ACQUIRE;
+    case OMP_MEMORY_ORDER_RELEASE: return MEMMODEL_RELEASE;
+    case OMP_MEMORY_ORDER_ACQ_REL: return MEMMODEL_ACQ_REL;
+    case OMP_MEMORY_ORDER_SEQ_CST: return MEMMODEL_SEQ_CST;
+    default: gcc_unreachable ();
+    }
+}
+
 /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
    operation as a normal volatile load.  */
 
@@ -6047,11 +6065,9 @@ expand_omp_atomic_load (basic_block load
   type = TREE_TYPE (loaded_val);
   itype = TREE_TYPE (TREE_TYPE (decl));
 
-  call = build_call_expr_loc (loc, decl, 2, addr,
-                             build_int_cst (NULL,
-                                            gimple_omp_atomic_seq_cst_p (stmt)
-                                            ? MEMMODEL_SEQ_CST
-                                            : MEMMODEL_RELAXED));
+  enum omp_memory_order omo = gimple_omp_atomic_memory_order (stmt);
+  tree mo = build_int_cst (NULL, omp_memory_order_to_memmodel (omo));
+  call = build_call_expr_loc (loc, decl, 2, addr, mo);
   if (!useless_type_conversion_p (type, itype))
     call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
   call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
@@ -6122,11 +6138,9 @@ expand_omp_atomic_store (basic_block loa
 
   if (!useless_type_conversion_p (itype, type))
     stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
-  call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
-                             build_int_cst (NULL,
-                                            gimple_omp_atomic_seq_cst_p (stmt)
-                                            ? MEMMODEL_SEQ_CST
-                                            : MEMMODEL_RELAXED));
+  enum omp_memory_order omo = gimple_omp_atomic_memory_order (stmt);
+  tree mo = build_int_cst (NULL, omp_memory_order_to_memmodel (omo));
+  call = build_call_expr_loc (loc, decl, 3, addr, stored_val, mo);
   if (exchange)
     {
       if (!useless_type_conversion_p (type, itype))
@@ -6167,7 +6181,6 @@ expand_omp_atomic_fetch_op (basic_block
   enum tree_code code;
   bool need_old, need_new;
   machine_mode imode;
-  bool seq_cst;
 
   /* We expect to find the following sequences:
 
@@ -6200,7 +6213,9 @@ expand_omp_atomic_fetch_op (basic_block
     return false;
   need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
   need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
-  seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
+  enum omp_memory_order omo
+    = gimple_omp_atomic_memory_order (last_stmt (load_bb));
+  enum memmodel mo = omp_memory_order_to_memmodel (omo);
   gcc_checking_assert (!need_old || !need_new);
 
   if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
@@ -6267,9 +6282,7 @@ expand_omp_atomic_fetch_op (basic_block
      use the RELAXED memory model.  */
   call = build_call_expr_loc (loc, decl, 3, addr,
                              fold_convert_loc (loc, itype, rhs),
-                             build_int_cst (NULL,
-                                            seq_cst ? MEMMODEL_SEQ_CST
-                                                    : MEMMODEL_RELAXED));
+                             build_int_cst (NULL, mo));
 
   if (need_old || need_new)
     {
--- gcc/omp-low.c.jj    2018-05-07 14:49:25.989113885 +0200
+++ gcc/omp-low.c       2018-05-30 13:23:20.421538876 +0200
@@ -5222,6 +5222,7 @@ lower_reduction_clauses (tree clauses, g
          ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
          x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
          x = build2 (OMP_ATOMIC, void_type_node, addr, x);
+         OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED;
          gimplify_and_add (x, stmt_seqp);
          return;
        }
--- gcc/tree-parloops.c.jj      2018-04-30 14:09:20.658406811 +0200
+++ gcc/tree-parloops.c 2018-05-31 17:16:38.219699594 +0200
@@ -1130,7 +1130,8 @@ create_call_for_reduction_1 (reduction_i
 
   tmp_load = create_tmp_var (TREE_TYPE (TREE_TYPE (addr)));
   tmp_load = make_ssa_name (tmp_load);
-  load = gimple_build_omp_atomic_load (tmp_load, addr);
+  load = gimple_build_omp_atomic_load (tmp_load, addr,
+                                      OMP_MEMORY_ORDER_RELAXED);
   SSA_NAME_DEF_STMT (tmp_load) = load;
   gsi = gsi_start_bb (new_bb);
   gsi_insert_after (&gsi, load, GSI_NEW_STMT);
@@ -1146,7 +1147,9 @@ create_call_for_reduction_1 (reduction_i
   name = force_gimple_operand_gsi (&gsi, x, true, NULL_TREE, true,
                                   GSI_CONTINUE_LINKING);
 
-  gsi_insert_after (&gsi, gimple_build_omp_atomic_store (name), GSI_NEW_STMT);
+  gimple *store = gimple_build_omp_atomic_store (name,
+                                                OMP_MEMORY_ORDER_RELAXED);
+  gsi_insert_after (&gsi, store, GSI_NEW_STMT);
   return 1;
 }
 
--- gcc/c-family/c-common.h.jj  2018-04-30 13:49:29.185791210 +0200
+++ gcc/c-family/c-common.h     2018-05-24 18:47:12.946486559 +0200
@@ -1147,8 +1147,8 @@ extern tree c_finish_omp_critical (locat
 extern tree c_finish_omp_ordered (location_t, tree, tree);
 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, bool,
-                                bool = false);
+                                tree, tree, tree, tree, tree, bool,
+                                enum omp_memory_order, bool = false);
 extern void c_finish_omp_flush (location_t);
 extern void c_finish_omp_taskwait (location_t);
 extern void c_finish_omp_taskyield (location_t);
--- gcc/c-family/c-omp.c.jj     2018-05-04 19:08:55.309273302 +0200
+++ gcc/c-family/c-omp.c        2018-05-24 18:47:57.278532992 +0200
@@ -184,8 +184,8 @@ c_finish_omp_taskyield (location_t loc)
 tree
 c_finish_omp_atomic (location_t loc, enum tree_code code,
                     enum tree_code opcode, tree lhs, tree rhs,
-                    tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst,
-                    bool test)
+                    tree v, tree lhs1, tree rhs1, bool swapped,
+                    enum omp_memory_order memory_order, bool test)
 {
   tree x, type, addr, pre = NULL_TREE;
   HOST_WIDE_INT bitpos = 0, bitsize = 0;
@@ -267,7 +267,7 @@ c_finish_omp_atomic (location_t loc, enu
     {
       x = build1 (OMP_ATOMIC_READ, type, addr);
       SET_EXPR_LOCATION (x, loc);
-      OMP_ATOMIC_SEQ_CST (x) = seq_cst;
+      OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
       if (blhs)
        x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
                        bitsize_int (bitsize), bitsize_int (bitpos));
@@ -318,7 +318,7 @@ c_finish_omp_atomic (location_t loc, enu
     type = void_type_node;
   x = build2 (code, type, addr, rhs);
   SET_EXPR_LOCATION (x, loc);
-  OMP_ATOMIC_SEQ_CST (x) = seq_cst;
+  OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
 
   /* Generally it is hard to prove lhs1 and lhs are the same memory
      location, just diagnose different variables.  */
--- gcc/c-family/c-pragma.c.jj  2018-04-30 13:49:29.351791569 +0200
+++ gcc/c-family/c-pragma.c     2018-05-30 10:16:26.973224443 +0200
@@ -1289,6 +1289,7 @@ static const struct omp_pragma_def omp_p
   { "end", PRAGMA_OMP_END_DECLARE_TARGET },
   { "flush", PRAGMA_OMP_FLUSH },
   { "master", PRAGMA_OMP_MASTER },
+  { "requires", PRAGMA_OMP_REQUIRES },
   { "section", PRAGMA_OMP_SECTION },
   { "sections", PRAGMA_OMP_SECTIONS },
   { "single", PRAGMA_OMP_SINGLE },
--- gcc/c-family/c-pragma.h.jj  2018-05-04 16:11:24.051925595 +0200
+++ gcc/c-family/c-pragma.h     2018-05-24 18:39:36.408008391 +0200
@@ -54,6 +54,7 @@ enum pragma_kind {
   PRAGMA_OMP_MASTER,
   PRAGMA_OMP_ORDERED,
   PRAGMA_OMP_PARALLEL,
+  PRAGMA_OMP_REQUIRES,
   PRAGMA_OMP_SECTION,
   PRAGMA_OMP_SECTIONS,
   PRAGMA_OMP_SIMD,
--- gcc/c/c-parser.c.jj 2018-05-07 14:53:05.722338632 +0200
+++ gcc/c/c-parser.c    2018-05-31 10:14:28.280595736 +0200
@@ -1459,6 +1459,7 @@ static void c_parser_omp_cancellation_po
 static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
 static void c_parser_omp_end_declare_target (c_parser *);
 static void c_parser_omp_declare (c_parser *, enum pragma_context);
+static void c_parser_omp_requires (c_parser *);
 static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
 static void c_parser_oacc_routine (c_parser *, enum pragma_context);
 
@@ -11056,6 +11057,10 @@ c_parser_pragma (c_parser *parser, enum
       c_parser_omp_declare (parser, context);
       return false;
 
+    case PRAGMA_OMP_REQUIRES:
+      c_parser_omp_requires (parser);
+      return false;     
+
     case PRAGMA_OMP_ORDERED:
       return c_parser_omp_ordered (parser, context, if_p);
 
@@ -12457,9 +12462,10 @@ c_parser_omp_clause_hint (c_parser *pars
 
       parens.skip_until_found_close (parser);
 
-      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+         || TREE_CODE (t) != INTEGER_CST)
        {
-         c_parser_error (parser, "expected integer expression");
+         c_parser_error (parser, "expected constant integer expression");
          return list;
        }
 
@@ -15424,62 +15430,157 @@ c_parser_omp_atomic (location_t loc, c_p
   tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
   tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
   tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
-  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+  enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
+  enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
   struct c_expr expr;
   location_t eloc;
   bool structured_block = false;
   bool swapped = false;
-  bool seq_cst = false;
   bool non_lvalue_p;
+  bool first = true;
+  tree clauses = NULL_TREE;
 
-  if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-      if (!strcmp (p, "seq_cst"))
-       {
-         seq_cst = true;
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_COMMA)
-             && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
-           c_parser_consume_token (parser);
-       }
-    }
-  if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
-      if (!strcmp (p, "read"))
-       code = OMP_ATOMIC_READ;
-      else if (!strcmp (p, "write"))
-       code = NOP_EXPR;
-      else if (!strcmp (p, "update"))
-       code = OMP_ATOMIC;
-      else if (!strcmp (p, "capture"))
-       code = OMP_ATOMIC_CAPTURE_NEW;
-      else
-       p = NULL;
-      if (p)
-       c_parser_consume_token (parser);
-    }
-  if (!seq_cst)
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
     {
-      if (c_parser_next_token_is (parser, CPP_COMMA)
-         && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
 
+      first = false;
+
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          const char *p
            = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-         if (!strcmp (p, "seq_cst"))
+         location_t cloc = c_parser_peek_token (parser)->location;
+         enum tree_code new_code = ERROR_MARK;
+         enum omp_memory_order new_memory_order
+           = OMP_MEMORY_ORDER_UNSPECIFIED;
+
+         if (!strcmp (p, "read"))
+           new_code = OMP_ATOMIC_READ;
+         else if (!strcmp (p, "write"))
+           new_code = NOP_EXPR;
+         else if (!strcmp (p, "update"))
+           new_code = OMP_ATOMIC;
+         else if (!strcmp (p, "capture"))
+           new_code = OMP_ATOMIC_CAPTURE_NEW;
+         else if (!strcmp (p, "seq_cst"))
+           new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         else if (!strcmp (p, "acq_rel"))
+           new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+         else if (!strcmp (p, "release"))
+           new_memory_order = OMP_MEMORY_ORDER_RELEASE;
+         else if (!strcmp (p, "acquire"))
+           new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+         else if (!strcmp (p, "relaxed"))
+           new_memory_order = OMP_MEMORY_ORDER_RELAXED;
+         else if (!strcmp (p, "hint"))
            {
-             seq_cst = true;
              c_parser_consume_token (parser);
+             clauses = c_parser_omp_clause_hint (parser, clauses);
+             continue;
+           }
+         else
+           {
+             p = NULL;
+             error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+                             "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
+                             "%<release%>, %<relaxed%> or %<hint%> clause");
+           }
+         if (p)
+           {
+             if (new_code != ERROR_MARK)
+               {
+                 if (code != ERROR_MARK)
+                   error_at (cloc, "too many atomic clauses");
+                 else
+                   code = new_code;
+               }
+             else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+               {
+                 if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+                   error_at (cloc, "too many memory order clauses");
+                 else
+                   memory_order = new_memory_order;
+               }
+             c_parser_consume_token (parser);
+             continue;
            }
        }
+      break;
     }
   c_parser_skip_to_pragma_eol (parser);
 
+  if (code == ERROR_MARK)
+    code = OMP_ATOMIC;
+  if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+    {
+      omp_requires_mask
+       = (enum omp_requires) (omp_requires_mask
+                              | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
+      switch ((enum omp_memory_order)
+             (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
+       {
+       case OMP_MEMORY_ORDER_UNSPECIFIED:
+       case OMP_MEMORY_ORDER_RELAXED:
+         memory_order = OMP_MEMORY_ORDER_RELAXED;
+         break;
+       case OMP_MEMORY_ORDER_SEQ_CST:
+         memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         break;
+       case OMP_MEMORY_ORDER_ACQ_REL:
+         switch (code)
+           {
+           case OMP_ATOMIC_READ:
+             memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+             break;
+           case NOP_EXPR: /* atomic write */
+           case OMP_ATOMIC:
+             memory_order = OMP_MEMORY_ORDER_RELEASE;
+             break;
+           default:
+             memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+             break;
+           }
+         break;
+       default:
+         gcc_unreachable ();
+       }
+    }
+  else
+    switch (code)
+      {
+      case OMP_ATOMIC_READ:
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_RELEASE)
+         {
+           error_at (loc, "%<#pragma omp atomic read%> incompatible with "
+                          "%<acq_rel%> or %<release%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      case NOP_EXPR: /* atomic write */
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+         {
+           error_at (loc, "%<#pragma omp atomic write%> incompatible with "
+                          "%<acq_rel%> or %<acquire%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      case OMP_ATOMIC:
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+         {
+           error_at (loc, "%<#pragma omp atomic update%> incompatible with "
+                          "%<acq_rel%> or %<acquire%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      default:
+       break;
+      }
+
   switch (code)
     {
     case OMP_ATOMIC_READ:
@@ -15796,7 +15897,7 @@ done:
     }
   else
     stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1,
-                               swapped, seq_cst);
+                               swapped, memory_order);
   if (stmt != error_mark_node)
     add_stmt (stmt);
 
@@ -15848,6 +15949,10 @@ c_parser_omp_critical (location_t loc, c
       else
        c_parser_error (parser, "expected identifier");
 
+      if (c_parser_next_token_is (parser, CPP_COMMA)
+         && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+       c_parser_consume_token (parser);
+
       clauses = c_parser_omp_all_clauses (parser,
                                          OMP_CRITICAL_CLAUSE_MASK,
                                          "#pragma omp critical");
@@ -17384,6 +17489,10 @@ c_parser_omp_target (c_parser *parser, e
       return false;
     }
 
+  if (flag_openmp)
+    omp_requires_mask
+      = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
@@ -18270,6 +18379,141 @@ c_parser_omp_declare (c_parser *parser,
   c_parser_skip_to_pragma_eol (parser);
 }
 
+/* OpenMP 5.0
+   #pragma omp requires clauses[optseq] new-line  */
+
+static void
+c_parser_omp_requires (c_parser *parser)
+{
+  bool first = true;
+  enum omp_requires new_req = (enum omp_requires) 0;
+
+  c_parser_consume_pragma (parser);
+
+  location_t loc = c_parser_peek_token (parser)->location;
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    {
+      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+
+      first = false;
+
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         const char *p
+           = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+         location_t cloc = c_parser_peek_token (parser)->location;
+         enum omp_requires this_req = (enum omp_requires) 0;
+
+         if (!strcmp (p, "unified_address"))
+           this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
+         else if (!strcmp (p, "unified_shared_memory"))
+           this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
+         else if (!strcmp (p, "dynamic_allocators"))
+           this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
+         else if (!strcmp (p, "reverse_offload"))
+           this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
+         else if (!strcmp (p, "atomic_default_mem_order"))
+           {
+             c_parser_consume_token (parser);
+
+             matching_parens parens;
+             if (parens.require_open (parser))
+               {
+                 if (c_parser_next_token_is (parser, CPP_NAME))
+                   {
+                     tree v = c_parser_peek_token (parser)->value;
+                     p = IDENTIFIER_POINTER (v);
+
+                     if (!strcmp (p, "seq_cst"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
+                     else if (!strcmp (p, "relaxed"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
+                     else if (!strcmp (p, "acq_rel"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
+                   }
+                 if (this_req == 0)
+                   {
+                     error_at (c_parser_peek_token (parser)->location,
+                               "expected %<seq_cst%>, %<relaxed%> or "
+                               "%<acq_rel%>");
+                     if (c_parser_peek_2nd_token (parser)->type
+                         == CPP_CLOSE_PAREN)
+                       c_parser_consume_token (parser);
+                   }
+                 else
+                   c_parser_consume_token (parser);
+
+                 parens.skip_until_found_close (parser);
+                 if (this_req == 0)
+                   {
+                     c_parser_skip_to_pragma_eol (parser, false);
+                     return;
+                   }
+               }
+             p = NULL;
+           }
+         else
+           {
+             error_at (cloc, "expected %<unified_address%>, "
+                             "%<unified_shared_memory%>, "
+                             "%<dynamic_allocators%>, "
+                              "%<reverse_offload%> "
+                              "or %<atomic_default_mem_order%> clause");
+             c_parser_skip_to_pragma_eol (parser, false);
+             return;
+           }
+         if (p)
+           c_parser_consume_token (parser);
+         if (this_req)
+           {
+             if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 if ((this_req & new_req) != 0)
+                   error_at (cloc, "too many %qs clauses", p);
+                 if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
+                     && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
+                   error_at (cloc, "%qs clause used lexically after first "
+                                   "target construct or offloading API", p);
+               }
+             else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 error_at (cloc, "too many %qs clauses",
+                           "atomic_default_mem_order");
+                 this_req = (enum omp_requires) 0;
+               }
+             else if ((omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 error_at (cloc, "more than one %<atomic_default_mem_order%>"
+                                 " clause in a single compilation unit");
+                 this_req
+                   = (enum omp_requires)
+                      (omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
+               }
+             else if ((omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
+               error_at (cloc, "%<atomic_default_mem_order%> clause used "
+                               "lexically after first %<atomic%> construct "
+                               "without memory order clause");
+             new_req = (enum omp_requires) (new_req | this_req);
+             omp_requires_mask
+               = (enum omp_requires) (omp_requires_mask | this_req);
+             continue;
+           }
+       }
+      break;
+    }
+  c_parser_skip_to_pragma_eol (parser);
+
+  if (new_req == 0)
+    error_at (loc, "%<pragma omp requires%> requires at least one clause");
+}
+
 /* OpenMP 4.5:
    #pragma omp taskloop taskloop-clause[optseq] new-line
      for-loop
--- gcc/cp/cp-tree.h.jj 2018-04-30 14:08:49.529329983 +0200
+++ gcc/cp/cp-tree.h    2018-05-31 12:12:24.497848922 +0200
@@ -4827,9 +4827,10 @@ more_aggr_init_expr_args_p (const aggr_i
   (TREE_LANG_FLAG_1 (SCOPE_REF_CHECK (NODE)))
 
 /* True for an OMP_ATOMIC that has dependent parameters.  These are stored
-   as an expr in operand 1, and integer_zero_node in operand 0.  */
+   as an expr in operand 1, and integer_zero_node or clauses in operand 0.  */
 #define OMP_ATOMIC_DEPENDENT_P(NODE) \
-  (TREE_CODE (TREE_OPERAND (OMP_ATOMIC_CHECK (NODE), 0)) == INTEGER_CST)
+  (TREE_CODE (TREE_OPERAND (OMP_ATOMIC_CHECK (NODE), 0)) == INTEGER_CST \
+   || TREE_CODE (TREE_OPERAND (OMP_ATOMIC_CHECK (NODE), 0)) == OMP_CLAUSE)
 
 /* Used while gimplifying continue statements bound to OMP_FOR nodes.  */
 #define OMP_FOR_GIMPLIFYING_P(NODE) \
@@ -6984,7 +6985,7 @@ extern tree finish_omp_for                        
(location_t
                                                 tree, tree, vec<tree> *, tree);
 extern void finish_omp_atomic                  (enum tree_code, enum tree_code,
                                                 tree, tree, tree, tree, tree,
-                                                bool);
+                                                tree, enum omp_memory_order);
 extern void finish_omp_barrier                 (void);
 extern void finish_omp_flush                   (void);
 extern void finish_omp_taskwait                        (void);
--- gcc/cp/parser.c.jj  2018-05-07 14:52:36.717319042 +0200
+++ gcc/cp/parser.c     2018-05-31 15:18:42.028880344 +0200
@@ -34492,62 +34492,154 @@ cp_parser_omp_atomic (cp_parser *parser,
 {
   tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
   tree rhs1 = NULL_TREE, orig_lhs;
-  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+  location_t loc = pragma_tok->location;
+  enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
+  enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
   bool structured_block = false;
-  bool seq_cst = false;
-
-  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);
-
-      if (!strcmp (p, "seq_cst"))
-       {
-         seq_cst = true;
-         cp_lexer_consume_token (parser->lexer);
-         if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
-             && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
-           cp_lexer_consume_token (parser->lexer);
-       }
-    }
-  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);
+  bool first = true;
+  tree clauses = NULL_TREE;
 
-      if (!strcmp (p, "read"))
-       code = OMP_ATOMIC_READ;
-      else if (!strcmp (p, "write"))
-       code = NOP_EXPR;
-      else if (!strcmp (p, "update"))
-       code = OMP_ATOMIC;
-      else if (!strcmp (p, "capture"))
-       code = OMP_ATOMIC_CAPTURE_NEW;
-      else
-       p = NULL;
-      if (p)
-       cp_lexer_consume_token (parser->lexer);
-    }
-  if (!seq_cst)
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
-      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
-         && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+      if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
        cp_lexer_consume_token (parser->lexer);
 
+      first = false;
+
       if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
        {
          tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+         location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
          const char *p = IDENTIFIER_POINTER (id);
-
-         if (!strcmp (p, "seq_cst"))
+         enum tree_code new_code = ERROR_MARK;
+         enum omp_memory_order new_memory_order
+           = OMP_MEMORY_ORDER_UNSPECIFIED;
+
+         if (!strcmp (p, "read"))
+           new_code = OMP_ATOMIC_READ;
+         else if (!strcmp (p, "write"))
+           new_code = NOP_EXPR;
+         else if (!strcmp (p, "update"))
+           new_code = OMP_ATOMIC;
+         else if (!strcmp (p, "capture"))
+           new_code = OMP_ATOMIC_CAPTURE_NEW;
+         else if (!strcmp (p, "seq_cst"))
+           new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         else if (!strcmp (p, "acq_rel"))
+           new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+         else if (!strcmp (p, "release"))
+           new_memory_order = OMP_MEMORY_ORDER_RELEASE;
+         else if (!strcmp (p, "acquire"))
+           new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+         else if (!strcmp (p, "relaxed"))
+           new_memory_order = OMP_MEMORY_ORDER_RELAXED;
+         else if (!strcmp (p, "hint"))
+           {
+             cp_lexer_consume_token (parser->lexer);
+             clauses = cp_parser_omp_clause_hint (parser, clauses, cloc);
+             continue;
+           }
+         else
+           {
+             p = NULL;
+             error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+                             "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
+                             "%<release%>, %<relaxed%> or %<hint%> clause");
+           }
+         if (p)
            {
-             seq_cst = true;
+             if (new_code != ERROR_MARK)
+               {
+                 if (code != ERROR_MARK)
+                   error_at (cloc, "too many atomic clauses");
+                 else
+                   code = new_code;
+               }
+             else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+               {
+                 if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+                   error_at (cloc, "too many memory order clauses");
+                 else
+                   memory_order = new_memory_order;
+               }
              cp_lexer_consume_token (parser->lexer);
+             continue;
            }
        }
+      break;
     }
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
+  if (code == ERROR_MARK)
+    code = OMP_ATOMIC;
+  if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+    {
+      omp_requires_mask
+       = (enum omp_requires) (omp_requires_mask
+                              | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
+      switch ((enum omp_memory_order)
+             (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
+       {
+       case OMP_MEMORY_ORDER_UNSPECIFIED:
+       case OMP_MEMORY_ORDER_RELAXED:
+         memory_order = OMP_MEMORY_ORDER_RELAXED;
+         break;
+       case OMP_MEMORY_ORDER_SEQ_CST:
+         memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         break;
+       case OMP_MEMORY_ORDER_ACQ_REL:
+         switch (code)
+           {
+           case OMP_ATOMIC_READ:
+             memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+             break;
+           case NOP_EXPR: /* atomic write */
+           case OMP_ATOMIC:
+             memory_order = OMP_MEMORY_ORDER_RELEASE;
+             break;
+           default:
+             memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+             break;
+           }
+         break;
+       default:
+         gcc_unreachable ();
+       }
+    }
+  else
+    switch (code)
+      {
+      case OMP_ATOMIC_READ:
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_RELEASE)
+         {
+           error_at (loc, "%<#pragma omp atomic read%> incompatible with "
+                          "%<acq_rel%> or %<release%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      case NOP_EXPR: /* atomic write */
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+         {
+           error_at (loc, "%<#pragma omp atomic write%> incompatible with "
+                          "%<acq_rel%> or %<acquire%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      case OMP_ATOMIC:
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+         {
+           error_at (loc, "%<#pragma omp atomic update%> incompatible with "
+                          "%<acq_rel%> or %<acquire%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      default:
+       break;
+      }
+
   switch (code)
     {
     case OMP_ATOMIC_READ:
@@ -34847,7 +34939,9 @@ stmt_done:
       cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
     }
 done:
-  finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, seq_cst);
+  clauses = finish_omp_clauses (clauses, C_ORT_OMP);
+  finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, clauses,
+                    memory_order);
   if (!structured_block)
     cp_parser_consume_semicolon_at_end_of_statement (parser);
   return;
@@ -34909,6 +35003,10 @@ cp_parser_omp_critical (cp_parser *parse
       if (name == error_mark_node)
        name = NULL;
 
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+         && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
+       cp_lexer_consume_token (parser->lexer);
+
       clauses = cp_parser_omp_all_clauses (parser,
                                           OMP_CRITICAL_CLAUSE_MASK,
                                           "#pragma omp critical", pragma_tok);
@@ -36753,6 +36851,10 @@ cp_parser_omp_target (cp_parser *parser,
 {
   tree *pc = NULL, stmt;
 
+  if (flag_openmp)
+    omp_requires_mask
+      = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -38123,6 +38225,147 @@ cp_parser_omp_declare (cp_parser *parser
   return false;
 }
 
+/* OpenMP 5.0
+   #pragma omp requires clauses[optseq] new-line  */
+
+static bool
+cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok)
+{
+  bool first = true;
+  enum omp_requires new_req = (enum omp_requires) 0;
+
+  location_t loc = pragma_tok->location;
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+    {
+      if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+
+      first = false;
+
+      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);
+         location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
+         enum omp_requires this_req = (enum omp_requires) 0;
+
+         if (!strcmp (p, "unified_address"))
+           this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
+         else if (!strcmp (p, "unified_shared_memory"))
+           this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
+         else if (!strcmp (p, "dynamic_allocators"))
+           this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
+         else if (!strcmp (p, "reverse_offload"))
+           this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
+         else if (!strcmp (p, "atomic_default_mem_order"))
+           {
+             cp_lexer_consume_token (parser->lexer);
+
+             matching_parens parens;
+             if (parens.require_open (parser))
+               {
+                 if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+                   {
+                     id = cp_lexer_peek_token (parser->lexer)->u.value;
+                     p = IDENTIFIER_POINTER (id);
+
+                     if (!strcmp (p, "seq_cst"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
+                     else if (!strcmp (p, "relaxed"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
+                     else if (!strcmp (p, "acq_rel"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
+                   }
+                 if (this_req == 0)
+                   {
+                     error_at (cp_lexer_peek_token (parser->lexer)->location,
+                               "expected %<seq_cst%>, %<relaxed%> or "
+                               "%<acq_rel%>");
+                     if (cp_lexer_nth_token_is (parser->lexer, 2,
+                                                CPP_CLOSE_PAREN))
+                       cp_lexer_consume_token (parser->lexer);
+                   }
+                 else
+                   cp_lexer_consume_token (parser->lexer);
+
+                 if (!parens.require_close (parser))
+                   cp_parser_skip_to_closing_parenthesis (parser,
+                                                          /*recovering=*/true,
+                                                          /*or_comma=*/false,
+                                                          /*consume_paren=*/
+                                                          true);
+
+                 if (this_req == 0)
+                   {
+                     cp_parser_require_pragma_eol (parser, pragma_tok);
+                     return false;
+                   }
+               }
+             p = NULL;
+           }
+         else
+           {
+             error_at (cloc, "expected %<unified_address%>, "
+                             "%<unified_shared_memory%>, "
+                             "%<dynamic_allocators%>, "
+                              "%<reverse_offload%> "
+                              "or %<atomic_default_mem_order%> clause");
+             cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+             return false;
+           }
+         if (p)
+           cp_lexer_consume_token (parser->lexer);
+         if (this_req)
+           {
+             if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 if ((this_req & new_req) != 0)
+                   error_at (cloc, "too many %qs clauses", p);
+                 if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
+                     && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
+                   error_at (cloc, "%qs clause used lexically after first "
+                                   "target construct or offloading API", p);
+               }
+             else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 error_at (cloc, "too many %qs clauses",
+                           "atomic_default_mem_order");
+                 this_req = (enum omp_requires) 0;
+               }
+             else if ((omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 error_at (cloc, "more than one %<atomic_default_mem_order%>"
+                                 " clause in a single compilation unit");
+                 this_req
+                   = (enum omp_requires)
+                      (omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
+               }
+             else if ((omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
+               error_at (cloc, "%<atomic_default_mem_order%> clause used "
+                               "lexically after first %<atomic%> construct "
+                               "without memory order clause");
+             new_req = (enum omp_requires) (new_req | this_req);
+             omp_requires_mask
+               = (enum omp_requires) (omp_requires_mask | this_req);
+             continue;
+           }
+       }
+      break;
+    }
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  if (new_req == 0)
+    error_at (loc, "%<pragma omp requires%> requires at least one clause");
+  return false;
+}
+
+
 /* OpenMP 4.5:
    #pragma omp taskloop taskloop-clause[optseq] new-line
      for-loop
@@ -39147,6 +39390,9 @@ cp_parser_pragma (cp_parser *parser, enu
       pop_omp_privatization_clauses (stmt);
       return true;
 
+    case PRAGMA_OMP_REQUIRES:
+      return cp_parser_omp_requires (parser, pragma_tok);
+
     case PRAGMA_OMP_ORDERED:
       if (context != pragma_stmt && context != pragma_compound)
        goto bad_stmt;
--- gcc/cp/pt.c.jj      2018-05-04 19:47:03.406932925 +0200
+++ gcc/cp/pt.c 2018-05-31 14:05:51.766473173 +0200
@@ -17289,6 +17289,10 @@ tsubst_expr (tree t, tree args, tsubst_f
 
     case OMP_ATOMIC:
       gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
+      tmp = NULL_TREE;
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == OMP_CLAUSE)
+       tmp = tsubst_omp_clauses (TREE_OPERAND (t, 0), C_ORT_OMP, args,
+                                 complain, in_decl);
       if (TREE_CODE (TREE_OPERAND (t, 1)) != MODIFY_EXPR)
        {
          tree op1 = TREE_OPERAND (t, 1);
@@ -17302,8 +17306,8 @@ tsubst_expr (tree t, tree args, tsubst_f
          lhs = RECUR (TREE_OPERAND (op1, 0));
          rhs = RECUR (TREE_OPERAND (op1, 1));
          finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
-                            NULL_TREE, NULL_TREE, rhs1,
-                            OMP_ATOMIC_SEQ_CST (t));
+                            NULL_TREE, NULL_TREE, rhs1, tmp,
+                            OMP_ATOMIC_MEMORY_ORDER (t));
        }
       else
        {
@@ -17340,8 +17344,8 @@ tsubst_expr (tree t, tree args, tsubst_f
              lhs = RECUR (TREE_OPERAND (op1, 0));
              rhs = RECUR (TREE_OPERAND (op1, 1));
            }
-         finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1,
-                            OMP_ATOMIC_SEQ_CST (t));
+         finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, tmp,
+                            OMP_ATOMIC_MEMORY_ORDER (t));
        }
       break;
 
--- gcc/cp/semantics.c.jj       2018-05-04 19:46:19.619888534 +0200
+++ gcc/cp/semantics.c  2018-05-31 15:18:22.659856911 +0200
@@ -7038,7 +7038,8 @@ finish_omp_clauses (tree clauses, enum c
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<priority%> expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<priority%> expression must be integral");
              remove = true;
            }
          else
@@ -7067,7 +7068,8 @@ finish_omp_clauses (tree clauses, enum c
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<num_tasks%> expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<hint%> expression must be integral");
              remove = true;
            }
          else
@@ -7077,6 +7079,13 @@ finish_omp_clauses (tree clauses, enum c
                {
                  t = maybe_constant_value (t);
                  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+                 if (TREE_CODE (t) != INTEGER_CST)
+                   {
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%<hint%> expression must be constant integer "
+                               "expression");
+                     remove = true;
+                   }
                }
              OMP_CLAUSE_HINT_EXPR (c) = t;
            }
@@ -8385,7 +8394,8 @@ finish_omp_for (location_t locus, enum t
 
 void
 finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
-                  tree rhs, tree v, tree lhs1, tree rhs1, bool seq_cst)
+                  tree rhs, tree v, tree lhs1, tree rhs1, tree clauses,
+                  enum omp_memory_order mo)
 {
   tree orig_lhs;
   tree orig_rhs;
@@ -8412,6 +8422,15 @@ finish_omp_atomic (enum tree_code code,
                     || (v && type_dependent_expression_p (v))
                     || (lhs1 && type_dependent_expression_p (lhs1))
                     || (rhs1 && type_dependent_expression_p (rhs1)));
+      if (clauses)
+       {
+         gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE
+                     && OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT
+                     && OMP_CLAUSE_CHAIN (clauses) == NULL_TREE);
+         if (type_dependent_expression_p (OMP_CLAUSE_HINT_EXPR (clauses))
+             || TREE_CODE (OMP_CLAUSE_HINT_EXPR (clauses)) != INTEGER_CST)
+           dependent_p = true;
+       }
       if (!dependent_p)
        {
          lhs = build_non_dependent_expr (lhs);
@@ -8454,7 +8473,7 @@ finish_omp_atomic (enum tree_code code,
          return;
        }
       stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
-                                 v, lhs1, rhs1, swapped, seq_cst,
+                                 v, lhs1, rhs1, swapped, mo,
                                  processing_template_decl != 0);
       if (stmt == error_mark_node)
        return;
@@ -8465,7 +8484,7 @@ finish_omp_atomic (enum tree_code code,
        {
          stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs),
                                   OMP_ATOMIC_READ, orig_lhs);
-         OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+         OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
          stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
        }
       else
@@ -8481,12 +8500,13 @@ finish_omp_atomic (enum tree_code code,
            {
              stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs1),
                                       code, orig_lhs1, stmt);
-             OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+             OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
              stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
            }
        }
-      stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
-      OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+      stmt = build2 (OMP_ATOMIC, void_type_node,
+                    clauses ? clauses : integer_zero_node, stmt);
+      OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
     }
   finish_expr_stmt (stmt);
 }
--- gcc/fortran/trans-openmp.c.jj       2018-05-02 17:52:01.091390796 +0200
+++ gcc/fortran/trans-openmp.c  2018-05-25 11:43:11.922496373 +0200
@@ -3158,7 +3158,9 @@ gfc_trans_omp_atomic (gfc_code *code)
   enum tree_code op = ERROR_MARK;
   enum tree_code aop = OMP_ATOMIC;
   bool var_on_left = false;
-  bool seq_cst = (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST) != 0;
+  enum omp_memory_order mo
+    = ((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST)
+       ? OMP_MEMORY_ORDER_SEQ_CST : OMP_MEMORY_ORDER_RELAXED);
 
   code = code->block->next;
   gcc_assert (code->op == EXEC_ASSIGN);
@@ -3190,7 +3192,7 @@ gfc_trans_omp_atomic (gfc_code *code)
       lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
 
       x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
-      OMP_ATOMIC_SEQ_CST (x) = seq_cst;
+      OMP_ATOMIC_MEMORY_ORDER (x) = mo;
       x = convert (TREE_TYPE (vse.expr), x);
       gfc_add_modify (&block, vse.expr, x);
 
@@ -3390,7 +3392,7 @@ gfc_trans_omp_atomic (gfc_code *code)
   if (aop == OMP_ATOMIC)
     {
       x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
-      OMP_ATOMIC_SEQ_CST (x) = seq_cst;
+      OMP_ATOMIC_MEMORY_ORDER (x) = mo;
       gfc_add_expr_to_block (&block, x);
     }
   else
@@ -3413,7 +3415,7 @@ gfc_trans_omp_atomic (gfc_code *code)
          gfc_add_block_to_block (&block, &lse.pre);
        }
       x = build2 (aop, type, lhsaddr, convert (type, x));
-      OMP_ATOMIC_SEQ_CST (x) = seq_cst;
+      OMP_ATOMIC_MEMORY_ORDER (x) = mo;
       x = convert (TREE_TYPE (vse.expr), x);
       gfc_add_modify (&block, vse.expr, x);
     }
--- gcc/testsuite/c-c++-common/gomp/atomic-17.c.jj      2018-05-25 
12:49:37.798876778 +0200
+++ gcc/testsuite/c-c++-common/gomp/atomic-17.c 2018-05-25 17:49:00.920080309 
+0200
@@ -0,0 +1,29 @@
+int i, v;
+float f;
+
+void
+foo ()
+{
+  #pragma omp atomic release, hint (0), update
+  i = i + 1;
+  #pragma omp atomic hint(0)seq_cst
+  i = i + 1;
+  #pragma omp atomic relaxed,update,hint (0)
+  i = i + 1;
+  #pragma omp atomic release
+  i = i + 1;
+  #pragma omp atomic relaxed
+  i = i + 1;
+  #pragma omp atomic acq_rel capture
+  v = i = i + 1;
+  #pragma omp atomic capture,acq_rel , hint (1)
+  v = i = i + 1;
+  #pragma omp atomic hint(0),acquire capture
+  v = i = i + 1;
+  #pragma omp atomic read acquire
+  v = i;
+  #pragma omp atomic release,write
+  i = v;
+  #pragma omp atomic hint(1),update,release
+  f = f + 2.0;
+}
--- gcc/testsuite/c-c++-common/gomp/atomic-18.c.jj      2018-05-25 
12:56:19.695198664 +0200
+++ gcc/testsuite/c-c++-common/gomp/atomic-18.c 2018-05-31 14:57:06.717293204 
+0200
@@ -0,0 +1,35 @@
+int i, v;
+float f;
+
+void
+foo (int j)
+{
+  #pragma omp atomic update,update     /* { dg-error "too many atomic clauses" 
} */
+  i = i + 1;
+  #pragma omp atomic seq_cst release   /* { dg-error "too many memory order 
clauses" } */
+  i = i + 1;
+  #pragma omp atomic read,release      /* { dg-error "incompatible with 
'acq_rel' or 'release' clauses" } */
+  v = i;
+  #pragma omp atomic acq_rel read      /* { dg-error "incompatible with 
'acq_rel' or 'release' clauses" } */
+  v = i;
+  #pragma omp atomic write acq_rel     /* { dg-error "incompatible with 
'acq_rel' or 'acquire' clauses" } */
+  i = v;
+  #pragma omp atomic acquire , write   /* { dg-error "incompatible with 
'acq_rel' or 'acquire' clauses" } */
+  i = v;
+  #pragma omp atomic update ,acquire   /* { dg-error "incompatible with 
'acq_rel' or 'acquire' clauses" } */
+  i = i + 1;
+  #pragma omp atomic acq_rel update    /* { dg-error "incompatible with 
'acq_rel' or 'acquire' clauses" } */
+  i = i + 1;
+  #pragma omp atomic acq_rel,hint(0)   /* { dg-error "incompatible with 
'acq_rel' or 'acquire' clauses" } */
+  i = i + 1;
+  #pragma omp atomic acquire           /* { dg-error "incompatible with 
'acq_rel' or 'acquire' clauses" } */
+  i = i + 1;
+  #pragma omp atomic capture hint (0) capture  /* { dg-error "too many atomic 
clauses" } */
+  v = i = i + 1;
+  #pragma omp atomic hint(j + 2)       /* { dg-error "constant integer 
expression" } */
+  i = i + 1;
+  #pragma omp atomic hint(f)           /* { dg-error "integ" } */
+  i = i + 1;
+  #pragma omp atomic foobar            /* { dg-error "expected 'read', 
'write', 'update', 'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 
'hint' clause" } */
+  i = i + 1;                           /* { dg-error "expected end of line 
before" "" { target *-*-* } .-1 } */
+}
--- gcc/testsuite/c-c++-common/gomp/atomic-19.c.jj      2018-05-25 
18:10:34.552694507 +0200
+++ gcc/testsuite/c-c++-common/gomp/atomic-19.c 2018-05-30 13:09:25.172575360 
+0200
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+/* { dg-final { scan-tree-dump-times "omp atomic release" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp atomic relaxed" 3 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp atomic read relaxed" 1 "original" } 
} */
+/* { dg-final { scan-tree-dump-times "omp atomic capture relaxed" 1 "original" 
} } */
+
+int i, j, k, l, m, n;
+
+void
+foo ()
+{
+  int v;
+  #pragma omp atomic release
+  i = i + 1;
+  #pragma omp requires atomic_default_mem_order (relaxed)
+  #pragma omp atomic
+  j = j + 1;
+  #pragma omp atomic update
+  k = k + 1;
+  #pragma omp atomic read
+  v = l;
+  #pragma omp atomic write
+  m = v;
+  #pragma omp atomic capture
+  v = n = n + 1;
+}
--- gcc/testsuite/c-c++-common/gomp/atomic-20.c.jj      2018-05-25 
18:58:00.922231550 +0200
+++ gcc/testsuite/c-c++-common/gomp/atomic-20.c 2018-05-30 13:10:09.887626937 
+0200
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+/* { dg-final { scan-tree-dump-times "omp atomic release" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp atomic seq_cst" 3 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp atomic read seq_cst" 1 "original" } 
} */
+/* { dg-final { scan-tree-dump-times "omp atomic capture seq_cst" 1 "original" 
} } */
+
+int i, j, k, l, m, n;
+
+void
+foo ()
+{
+  int v;
+  #pragma omp atomic release
+  i = i + 1;
+  #pragma omp requires atomic_default_mem_order (seq_cst)
+  #pragma omp atomic
+  j = j + 1;
+  #pragma omp atomic update
+  k = k + 1;
+  #pragma omp atomic read
+  v = l;
+  #pragma omp atomic write
+  m = v;
+  #pragma omp atomic capture
+  v = n = n + 1;
+}
--- gcc/testsuite/c-c++-common/gomp/atomic-21.c.jj      2018-05-25 
18:58:44.042281890 +0200
+++ gcc/testsuite/c-c++-common/gomp/atomic-21.c 2018-05-30 13:16:16.974050397 
+0200
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+/* { dg-final { scan-tree-dump-times "omp atomic release" 4 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp atomic read acquire" 1 "original" } 
} */
+/* { dg-final { scan-tree-dump-times "omp atomic capture acq_rel" 1 "original" 
} } */
+
+int i, j, k, l, m, n;
+
+void
+foo ()
+{
+  int v;
+  #pragma omp atomic release
+  i = i + 1;
+  #pragma omp requires atomic_default_mem_order (acq_rel)
+  #pragma omp atomic
+  j = j + 1;
+  #pragma omp atomic update
+  k = k + 1;
+  #pragma omp atomic read
+  v = l;
+  #pragma omp atomic write
+  m = v;
+  #pragma omp atomic capture
+  v = n = n + 1;
+}
--- gcc/testsuite/c-c++-common/gomp/atomic-22.c.jj      2018-05-30 
12:47:29.730146069 +0200
+++ gcc/testsuite/c-c++-common/gomp/atomic-22.c 2018-05-30 12:48:41.096223146 
+0200
@@ -0,0 +1,12 @@
+int i, j;
+
+void
+foo ()
+{
+  int v;
+  #pragma omp atomic release
+  i = i + 1;
+  #pragma omp atomic read
+  v = j;
+  #pragma omp requires atomic_default_mem_order (acq_rel)      /* { dg-error 
"'atomic_default_mem_order' clause used lexically after first 'atomic' 
construct without memory order clause" } */
+}
--- gcc/testsuite/c-c++-common/gomp/critical-1.c.jj     2018-05-30 
10:53:58.338836851 +0200
+++ gcc/testsuite/c-c++-common/gomp/critical-1.c        2018-05-30 
11:02:20.740381105 +0200
@@ -0,0 +1,14 @@
+int i;
+
+void
+foo (void)
+{
+  #pragma omp critical
+  i = i + 1;
+  #pragma omp critical (foo)
+  i = i + 1;
+  #pragma omp critical (foo) hint (0)
+  i = i + 1;
+  #pragma omp critical (foo),hint(1)
+  i = i + 1;
+}
--- gcc/testsuite/c-c++-common/gomp/critical-2.c.jj     2018-05-30 
10:58:44.402143826 +0200
+++ gcc/testsuite/c-c++-common/gomp/critical-2.c        2018-05-31 
13:30:23.772716780 +0200
@@ -0,0 +1,10 @@
+int i;
+
+void
+foo (int j)
+{
+  #pragma omp critical (foo) hint (j + 1)      /* { dg-error "constant integer 
expression" } */
+  i = i + 1;
+  #pragma omp critical (foo),hint(j)           /* { dg-error "constant integer 
expression" } */
+  i = i + 1;
+}
--- gcc/testsuite/c-c++-common/gomp/requires-1.c.jj     2018-05-30 
11:08:22.356777523 +0200
+++ gcc/testsuite/c-c++-common/gomp/requires-1.c        2018-05-30 
11:34:49.139466432 +0200
@@ -0,0 +1,15 @@
+#pragma omp requires unified_address
+#pragma omp requires unified_shared_memory
+#pragma omp requires unified_shared_memory unified_address
+#pragma omp requires dynamic_allocators,reverse_offload
+
+int i;
+
+void
+foo ()
+{
+  if (0)
+    #pragma omp requires unified_shared_memory unified_address
+    i++;
+  #pragma omp requries atomic_default_mem_order(seq_cst)
+}
--- gcc/testsuite/c-c++-common/gomp/requires-2.c.jj     2018-05-30 
11:36:46.932579387 +0200
+++ gcc/testsuite/c-c++-common/gomp/requires-2.c        2018-05-31 
13:41:24.832409848 +0200
@@ -0,0 +1,18 @@
+#pragma omp requires   /* { dg-error "requires at least one clause" } */
+#pragma omp requires unified_shared_memory,unified_shared_memory       /* { 
dg-error "too many 'unified_shared_memory' clauses" } */
+#pragma omp requires unified_address   unified_address /* { dg-error "too many 
'unified_address' clauses" } */
+#pragma omp requires reverse_offload reverse_offload   /* { dg-error "too many 
'reverse_offload' clauses" } */
+#pragma omp requires foobarbaz /* { dg-error "expected 'unified_address', 
'unified_shared_memory', 'dynamic_allocators', 'reverse_offload' or 
'atomic_default_mem_order' clause" } */
+
+int i;
+
+void
+foo ()
+{
+  #pragma omp requires dynamic_allocators , dynamic_allocators /* { dg-error 
"too many 'dynamic_allocators' clauses" } */
+  if (0)
+    #pragma omp requires atomic_default_mem_order(seq_cst) 
atomic_default_mem_order(seq_cst)   /* { dg-error "too many 
'atomic_default_mem_order' clauses" } */
+    i++;
+}
+
+#pragma omp requires atomic_default_mem_order (seq_cst)        /* { dg-error 
"more than one 'atomic_default_mem_order' clause in a single compilation unit" 
} */
--- gcc/testsuite/c-c++-common/gomp/requires-3.c.jj     2018-05-30 
12:32:11.106153923 +0200
+++ gcc/testsuite/c-c++-common/gomp/requires-3.c        2018-05-30 
12:46:00.914050144 +0200
@@ -0,0 +1,3 @@
+#pragma omp requires atomic_default_mem_order(acquire) /* { dg-error "expected 
'seq_cst', 'relaxed' or 'acq_rel'" } */
+#pragma omp requires atomic_default_mem_order(release) /* { dg-error "expected 
'seq_cst', 'relaxed' or 'acq_rel'" } */
+#pragma omp requires atomic_default_mem_order(foobar)  /* { dg-error "expected 
'seq_cst', 'relaxed' or 'acq_rel'" } */
--- gcc/testsuite/c-c++-common/gomp/requires-4.c.jj     2018-05-30 
12:59:39.022931562 +0200
+++ gcc/testsuite/c-c++-common/gomp/requires-4.c        2018-05-30 
13:00:29.172985548 +0200
@@ -0,0 +1,11 @@
+#pragma omp requires unified_shared_memory,unified_address,reverse_offload
+void
+foo (void)
+{
+  #pragma omp target
+  ;
+  #pragma omp requires unified_shared_memory   /* { dg-error 
"'unified_shared_memory' clause used lexically after first target construct or 
offloading API" } */
+}
+
+#pragma omp requires unified_address   /* { dg-error "'unified_address' clause 
used lexically after first target construct or offloading API" } */
+#pragma omp requires reverse_offload   /* { dg-error "'reverse_offload' clause 
used lexically after first target construct or offloading API" } */
--- gcc/testsuite/gcc.dg/gomp/atomic-5.c.jj     2017-05-04 15:05:34.766845417 
+0200
+++ gcc/testsuite/gcc.dg/gomp/atomic-5.c        2018-05-30 13:29:27.924158256 
+0200
@@ -27,7 +27,7 @@ void f1(void)
   #pragma omp atomic
     bar() += 1;                /* { dg-error "lvalue required" } */
   #pragma omp atomic a /* { dg-error "expected end of line" } */
-    x++;
+    x++;               /* { dg-error "expected 'read', 'write', 'update', 
'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { 
target *-*-* } .-1 } */
   #pragma omp atomic
     ;                  /* { dg-error "expected expression" } */
   #pragma omp atomic
--- gcc/testsuite/g++.dg/gomp/atomic-18.C.jj    2018-05-31 13:54:14.616564515 
+0200
+++ gcc/testsuite/g++.dg/gomp/atomic-18.C       2018-05-31 14:45:03.629414404 
+0200
@@ -0,0 +1,50 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-original" }
+// { dg-final { scan-tree-dump-times "omp atomic release" 5 "original" } }
+// { dg-final { scan-tree-dump-times "omp atomic seq_cst" 1 "original" } }
+// { dg-final { scan-tree-dump-times "omp atomic relaxed" 2 "original" } }
+// { dg-final { scan-tree-dump-times "omp atomic capture acq_rel" 3 "original" 
} }
+// { dg-final { scan-tree-dump-times "omp atomic capture acquire" 1 "original" 
} }
+// { dg-final { scan-tree-dump-times "omp atomic read acquire" 1 "original" } }
+
+int i, v;
+float f;
+
+template <int N, int M, typename T>
+void
+foo (T *p)
+{
+  #pragma omp atomic release, hint (N), update
+  i = i + 1;
+  #pragma omp atomic hint(0)seq_cst
+  i = i + 1;
+  #pragma omp atomic relaxed,update,hint (N)
+  i = i + 1;
+  #pragma omp atomic release
+  i = i + 1;
+  #pragma omp atomic relaxed
+  i = i + 1;
+  #pragma omp atomic acq_rel capture
+  v = i = i + 1;
+  #pragma omp atomic capture,acq_rel , hint (M)
+  v = i = i + 1;
+  #pragma omp atomic hint(N),acquire capture
+  v = i = i + 1;
+  #pragma omp atomic read acquire
+  v = i;
+  #pragma omp atomic release,write
+  i = v;
+  #pragma omp atomic hint(1),update,release
+  f = f + 2.0;
+  #pragma omp requires atomic_default_mem_order (acq_rel)
+  #pragma omp atomic hint (M - 1) update
+  *p += 1;
+  #pragma omp atomic capture, hint (M)
+  v = *p = *p + 1;
+}
+
+void
+bar ()
+{
+  foo <0, 1, int> (&i);
+}
--- gcc/testsuite/g++.dg/gomp/atomic-19.C.jj    2018-05-31 14:57:32.911325953 
+0200
+++ gcc/testsuite/g++.dg/gomp/atomic-19.C       2018-05-31 15:00:47.295569027 
+0200
@@ -0,0 +1,17 @@
+int i;
+
+template <int N, typename T>
+void
+foo (T x)
+{
+  #pragma omp atomic hint (x)          // { dg-error "must be integral" }
+  i = i + 1;
+  #pragma omp atomic hint (N + i)      // { dg-error "constant integer 
expression" }
+  i = i + 1;
+}
+
+void
+bar ()
+{
+  foo <0, float> (1.0f);
+}
--- gcc/testsuite/g++.dg/gomp/atomic-5.C.jj     2017-05-04 15:05:46.000000000 
+0200
+++ gcc/testsuite/g++.dg/gomp/atomic-5.C        2018-05-31 13:45:33.963710644 
+0200
@@ -23,7 +23,7 @@ void f1(void)
   #pragma omp atomic
     bar() += 1;                /* { dg-error "lvalue required" } */
   #pragma omp atomic a /* { dg-error "expected end of line" } */
-    x++;
+    x++;               /* { dg-error "expected 'read', 'write', 'update', 
'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { 
target *-*-* } .-1 } */
   #pragma omp atomic
     ;                  /* { dg-error "expected primary-expression" } */
   #pragma omp atomic
--- gcc/testsuite/g++.dg/gomp/critical-3.C.jj   2018-05-31 15:12:26.569426148 
+0200
+++ gcc/testsuite/g++.dg/gomp/critical-3.C      2018-05-31 16:29:27.756617626 
+0200
@@ -0,0 +1,33 @@
+int i;
+
+template <int N>
+void
+foo (void)
+{
+  #pragma omp critical (foo), hint (N + 1)
+  i++;
+}
+
+template <int N>
+void
+bar (void)
+{
+  #pragma omp critical (bar), hint (N + i)     // { dg-error "constant integer 
expression" }
+  i++;
+}
+
+template <typename T>
+void
+baz (T x)
+{
+  #pragma omp critical (baz) hint (x)  // { dg-error "expression must be 
integral" }
+  i++;
+}
+
+void
+test ()
+{
+  foo <0> ();
+  bar <0> ();
+  baz (0.0);
+}

        Jakub

Reply via email to