]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Add support for OpenMP 5.1 atomics for C++
authorJakub Jelinek <jakub@redhat.com>
Fri, 17 Sep 2021 13:20:20 +0000 (15:20 +0200)
committerTobias Burnus <tobias@codesourcery.com>
Fri, 17 Sep 2021 13:20:20 +0000 (15:20 +0200)
Besides the C++ FE changes, I've noticed that the C FE didn't reject
  #pragma omp atomic capture compare
  { v = x; x = y; }
and other forms of atomic swap, this patch fixes that too.  And the
c-family/ routine needed quite a few changes so that the new code
in it works fine with both FEs.

2021-09-17  Jakub Jelinek  <jakub@redhat.com>

gcc/c-family/
* c-omp.c (c_finish_omp_atomic): Avoid creating
TARGET_EXPR if test is true, use create_tmp_var_raw instead of
create_tmp_var and add a zero initializer to TARGET_EXPRs that
had NULL initializer.  When omitting operands after v = x,
use type of v rather than type of x.  Fix type of vtmp
TARGET_EXPR.
gcc/c/
* c-parser.c (c_parser_omp_atomic): Reject atomic swap if capture
is true.
gcc/cp/
* cp-tree.h (finish_omp_atomic): Add r and weak arguments.
* parser.c (cp_parser_omp_atomic): Update function comment for
OpenMP 5.1 atomics, parse OpenMP 5.1 atomics and fail, compare and
weak clauses.
* semantics.c (finish_omp_atomic): Add r and weak arguments, handle
them, handle COND_EXPRs.
* pt.c (tsubst_expr): Adjust for COND_EXPR forms that
finish_omp_atomic can now produce.
gcc/testsuite/
* c-c++-common/gomp/atomic-18.c: Expect same diagnostics in C++ as in
C.
* c-c++-common/gomp/atomic-25.c: Drop c effective target.
* c-c++-common/gomp/atomic-26.c: Likewise.
* c-c++-common/gomp/atomic-27.c: Likewise.
* c-c++-common/gomp/atomic-28.c: Likewise.
* c-c++-common/gomp/atomic-29.c: Likewise.
* c-c++-common/gomp/atomic-30.c: Likewise.  Adjust expected diagnostics
for C++ when it differs from C.
(foo): Change return type from double to void.
* g++.dg/gomp/atomic-5.C: Adjust expected diagnostics wording.
* g++.dg/gomp/atomic-20.C: New test.
libgomp/
* testsuite/libgomp.c-c++-common/atomic-19.c: Drop c effective target.
Use /* */ comments instead of //.
* testsuite/libgomp.c-c++-common/atomic-20.c: Likewise.
* testsuite/libgomp.c-c++-common/atomic-21.c: Likewise.
* testsuite/libgomp.c++/atomic-16.C: New test.
* testsuite/libgomp.c++/atomic-17.C: New test.

(cherry picked from commit 3a2bcffac602f5de56537a77db1062984bcefd45)

25 files changed:
gcc/c-family/ChangeLog.omp
gcc/c-family/c-omp.c
gcc/c/ChangeLog.omp
gcc/c/c-parser.c
gcc/cp/ChangeLog.omp
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog.omp
gcc/testsuite/c-c++-common/gomp/atomic-18.c
gcc/testsuite/c-c++-common/gomp/atomic-25.c
gcc/testsuite/c-c++-common/gomp/atomic-26.c
gcc/testsuite/c-c++-common/gomp/atomic-27.c
gcc/testsuite/c-c++-common/gomp/atomic-28.c
gcc/testsuite/c-c++-common/gomp/atomic-29.c
gcc/testsuite/c-c++-common/gomp/atomic-30.c
gcc/testsuite/g++.dg/gomp/atomic-20.C [new file with mode: 0644]
gcc/testsuite/g++.dg/gomp/atomic-5.C
libgomp/ChangeLog.omp
libgomp/testsuite/libgomp.c++/atomic-16.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-17.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c-c++-common/atomic-19.c
libgomp/testsuite/libgomp.c-c++-common/atomic-20.c
libgomp/testsuite/libgomp.c-c++-common/atomic-21.c

index 64e3e58ddd9e7f172f21583816a4c894539bd7f2..4ad9b2fbb06bcc1c26134f825525f3057f3f3259 100644 (file)
@@ -1,3 +1,15 @@
+2021-09-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-omp.c (c_finish_omp_atomic): Avoid creating
+       TARGET_EXPR if test is true, use create_tmp_var_raw instead of
+       create_tmp_var and add a zero initializer to TARGET_EXPRs that
+       had NULL initializer.  When omitting operands after v = x,
+       use type of v rather than type of x.  Fix type of vtmp
+       TARGET_EXPR.
+
 2021-09-13  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index b4201f0b1d6bbad10a15cee65a4c261576393443..b4c611d1a1ea35a375ab700028047c37a342ab5d 100644 (file)
@@ -377,7 +377,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
        return error_mark_node;
       gcc_assert (TREE_CODE (rhs1) == EQ_EXPR);
       tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0));
-      if (SCALAR_FLOAT_TYPE_P (cmptype))
+      if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
        {
          bool clear_padding = false;
          if (BITS_PER_UNIT == 8 && CHAR_BIT == 8)
@@ -444,12 +444,14 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
                }
            }
        }
-      if (r)
+      if (r && test)
+       rtmp = rhs1;
+      else if (r)
        {
-         tree var = create_tmp_var (boolean_type_node);
+         tree var = create_tmp_var_raw (boolean_type_node);
          DECL_CONTEXT (var) = current_function_decl;
          rtmp = build4 (TARGET_EXPR, boolean_type_node, var,
-                        NULL, NULL, NULL);
+                        boolean_false_node, NULL, NULL);
          save = in_late_binary_op;
          in_late_binary_op = true;
          x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR,
@@ -530,14 +532,11 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
            }
        }
       if (blhs)
+       x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
+                       bitsize_int (bitsize), bitsize_int (bitpos));
+      if (r && !test)
        {
-         x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
-                         bitsize_int (bitsize), bitsize_int (bitpos));
-         type = TREE_TYPE (blhs);
-       }
-      if (r)
-       {
-         vtmp = create_tmp_var (TREE_TYPE (x));
+         vtmp = create_tmp_var_raw (TREE_TYPE (x));
          DECL_CONTEXT (vtmp) = current_function_decl;
        }
       else
@@ -546,10 +545,11 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
                             loc, x, NULL_TREE);
       if (x == error_mark_node)
        return error_mark_node;
-      if (r)
+      type = TREE_TYPE (x);
+      if (r && !test)
        {
-         vtmp = build4 (TARGET_EXPR, boolean_type_node, vtmp,
-                        NULL, NULL, NULL);
+         vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
+                        build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
          gcc_assert (TREE_CODE (x) == MODIFY_EXPR
                      && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp));
          TREE_OPERAND (x, 0) = vtmp;
index 1616774d7e0409e526a693f8dca0191dbee0991b..2de700d30d0170cd13b830a53d3d04244d427806 100644 (file)
@@ -1,3 +1,11 @@
+2021-09-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-parser.c (c_parser_omp_atomic): Reject atomic swap if capture
+       is true.
+
 2021-09-13  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 342c0d3fa1b7eaa2307929da3ce8e8fdc830bb49..087f3e37f80120a81525830ab493928d3eb7dcf5 100644 (file)
@@ -18524,7 +18524,7 @@ restart:
                  c_parser_consume_token (parser);
                  goto restart;
                }
-             if (structured_block)
+             if (structured_block && !compare)
                {
                  opcode = NOP_EXPR;
                  expr = default_function_array_read_conversion (eloc, expr);
index 14ee9e6b179625468bcebfe859247a51e109e869..aefee5122131532ee135ba7e35b6b415266d2db7 100644 (file)
@@ -1,3 +1,17 @@
+2021-09-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * cp-tree.h (finish_omp_atomic): Add r and weak arguments.
+       * parser.c (cp_parser_omp_atomic): Update function comment for
+       OpenMP 5.1 atomics, parse OpenMP 5.1 atomics and fail, compare and
+       weak clauses.
+       * semantics.c (finish_omp_atomic): Add r and weak arguments, handle
+       them, handle COND_EXPRs.
+       * pt.c (tsubst_expr): Adjust for COND_EXPR forms that
+       finish_omp_atomic can now produce.
+
 2021-09-13  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index ee0d3cf789b3e5653d8821deafe17ac77919534e..829998832376b21ffa29c6c792348cac7af05c34 100644 (file)
@@ -7523,8 +7523,8 @@ extern tree finish_omp_for                        (location_t, enum tree_code,
 extern tree finish_omp_for_block               (tree, tree);
 extern void finish_omp_atomic                  (location_t, enum tree_code,
                                                 enum tree_code, tree, tree,
-                                                tree, tree, tree, tree,
-                                                enum omp_memory_order);
+                                                tree, tree, tree, tree, tree,
+                                                enum omp_memory_order, bool);
 extern void finish_omp_barrier                 (void);
 extern void finish_omp_depobj                  (location_t, tree,
                                                 enum omp_clause_depend_kind,
index b1a6c8841b764f536f0ee7145cb6cc71318e8eaf..02944e2164d702f3c32296eec15704797e769881 100644 (file)
@@ -39872,19 +39872,56 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok)
    capture-block:
      { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
 
-  where x and v are lvalue expressions with scalar type.  */
+   OpenMP 5.1:
+   # pragma omp atomic compare new-line
+     conditional-update-atomic
+
+   # pragma omp atomic compare capture new-line
+     conditional-update-capture-atomic
+
+   conditional-update-atomic:
+     cond-expr-stmt | cond-update-stmt
+   cond-expr-stmt:
+     x = expr ordop x ? expr : x;
+     x = x ordop expr ? expr : x;
+     x = x == e ? d : x;
+   cond-update-stmt:
+     if (expr ordop x) { x = expr; }
+     if (x ordop expr) { x = expr; }
+     if (x == e) { x = d; }
+   ordop:
+     <, >
+   conditional-update-capture-atomic:
+     v = cond-expr-stmt
+     { v = x; cond-expr-stmt }
+     { cond-expr-stmt v = x; }
+     { v = x; cond-update-stmt }
+     { cond-update-stmt v = x; }
+     if (x == e) { x = d; } else { v = x; }
+     { r = x == e; if (r) { x = d; } }
+     { r = x == e; if (r) { x = d; } else { v = x; } }
+
+  where x, r and v are lvalue expressions with scalar type,
+  expr, e and d are expressions with scalar type and e might be
+  the same as v.  */
 
 static void
 cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
 {
   tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
-  tree rhs1 = NULL_TREE, orig_lhs;
+  tree rhs1 = NULL_TREE, orig_lhs, r = NULL_TREE;
   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 first = true;
   tree clauses = NULL_TREE;
+  bool capture = false;
+  bool compare = false;
+  bool weak = false;
+  enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+  bool no_semicolon = false;
+  bool extra_scope = false;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
@@ -39904,6 +39941,10 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
          enum tree_code new_code = ERROR_MARK;
          enum omp_memory_order new_memory_order
            = OMP_MEMORY_ORDER_UNSPECIFIED;
+         bool new_capture = false;
+         bool new_compare = false;
+         bool new_weak = false;
+         enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
 
          if (!strcmp (p, "read"))
            new_code = OMP_ATOMIC_READ;
@@ -39911,7 +39952,7 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
            new_code = NOP_EXPR;
          else if (!strcmp (p, "update"))
            new_code = OMP_ATOMIC;
-         else if (!strcmp (p, "capture"))
+         else if (openacc && !strcmp (p, "capture"))
            new_code = OMP_ATOMIC_CAPTURE_NEW;
          else if (openacc)
            {
@@ -39919,6 +39960,52 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
              error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
                              "or %<capture%> clause");
            }
+         else if (!strcmp (p, "capture"))
+           new_capture = true;
+         else if (!strcmp (p, "compare"))
+           new_compare = true;
+         else if (!strcmp (p, "weak"))
+           new_weak = true;
+         else if (!strcmp (p, "fail"))
+           {
+             matching_parens parens;
+
+             cp_lexer_consume_token (parser->lexer);
+             if (!parens.require_open (parser))
+               continue;
+
+             if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+               {
+                 id = cp_lexer_peek_token (parser->lexer)->u.value;
+                 const char *q = IDENTIFIER_POINTER (id);
+
+                 if (!strcmp (q, "seq_cst"))
+                   new_fail = OMP_MEMORY_ORDER_SEQ_CST;
+                 else if (!strcmp (q, "acquire"))
+                   new_fail = OMP_MEMORY_ORDER_ACQUIRE;
+                 else if (!strcmp (q, "relaxed"))
+                   new_fail = OMP_MEMORY_ORDER_RELAXED;
+               }
+
+             if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+               {
+                 cp_lexer_consume_token (parser->lexer);
+                 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+                   error_at (cloc, "too many %qs clauses", "fail");
+                 else
+                   fail = new_fail;
+               }
+             else
+               cp_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
+                                        "or %<relaxed%>");
+             if (new_fail == OMP_MEMORY_ORDER_UNSPECIFIED
+                 || !parens.require_close (parser))
+               cp_parser_skip_to_closing_parenthesis (parser,
+                                                      /*recovering=*/true,
+                                                      /*or_comma=*/false,
+                                                      /*consume_paren=*/true);
+             continue;
+           }
          else if (!strcmp (p, "seq_cst"))
            new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
          else if (!strcmp (p, "acq_rel"))
@@ -39939,8 +40026,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
            {
              p = NULL;
              error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
-                             "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
-                             "%<release%>, %<relaxed%> or %<hint%> clause");
+                             "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
+                             "%<seq_cst%>, %<acq_rel%>, %<release%>, "
+                             "%<relaxed%> or %<hint%> clause");
            }
          if (p)
            {
@@ -39963,6 +40051,27 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
                  else
                    memory_order = new_memory_order;
                }
+             else if (new_capture)
+               {
+                 if (capture)
+                   error_at (cloc, "too many %qs clauses", "capture");
+                 else
+                   capture = true;
+               }
+             else if (new_compare)
+               {
+                 if (compare)
+                   error_at (cloc, "too many %qs clauses", "compare");
+                 else
+                   compare = true;
+               }
+             else if (new_weak)
+               {
+                 if (weak)
+                   error_at (cloc, "too many %qs clauses", "weak");
+                 else
+                   weak = true;
+               }
              cp_lexer_consume_token (parser->lexer);
              continue;
            }
@@ -39973,6 +40082,30 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
 
   if (code == ERROR_MARK)
     code = OMP_ATOMIC;
+  if (capture)
+    {
+      if (code != OMP_ATOMIC)
+       error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+                      "clauses", "capture");
+      else
+       code = OMP_ATOMIC_CAPTURE_NEW;
+    }
+  if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
+    {
+      error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+                    "clauses", "compare");
+      compare = false;
+    }
+  if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
+    {
+      error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
+      fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+    }
+  if (weak && !compare)
+    {
+      error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
+      weak = false;
+    }
   if (openacc)
     memory_order = OMP_MEMORY_ORDER_RELAXED;
   else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
@@ -40034,6 +40167,10 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
       default:
        break;
       }
+  if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+    memory_order
+      = (enum omp_memory_order) (memory_order
+                                | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
 
   switch (code)
     {
@@ -40066,6 +40203,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
          cp_lexer_consume_token (parser->lexer);
          structured_block = true;
        }
+      else if (compare
+              && cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+       break;
       else
        {
          v = cp_parser_unary_expression (parser);
@@ -40073,12 +40213,179 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
            goto saw_error;
          if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
            goto saw_error;
+         if (compare
+             && cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+           {
+             location_t eloc = cp_lexer_peek_token (parser->lexer)->location;
+             error_at (eloc, "expected expression");
+             goto saw_error;
+           }
        }
     default:
       break;
     }
 
 restart:
+  if (compare && cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+    {
+      cp_lexer_consume_token (parser->lexer);
+
+      matching_parens parens;
+      if (!parens.require_open (parser))
+       goto saw_error;
+      location_t eloc = cp_lexer_peek_token (parser->lexer)->location;
+      tree cmp_expr;
+      if (r)
+       cmp_expr = cp_parser_unary_expression (parser);
+      else
+       cmp_expr = cp_parser_binary_expression (parser, false, true,
+                                               PREC_NOT_OPERATOR, NULL);
+      if (!parens.require_close (parser))
+       cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      if (cmp_expr == error_mark_node)
+       goto saw_error;
+      if (r)
+       {
+         if (!cp_tree_equal (cmp_expr, r))
+           goto bad_if;
+         cmp_expr = rhs;
+         rhs = NULL_TREE;
+         gcc_assert (TREE_CODE (cmp_expr) == EQ_EXPR);
+       }
+      if (TREE_CODE (cmp_expr) == EQ_EXPR)
+       ;
+      else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+       {
+         error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc),
+                   "expected %<==%> comparison in %<if%> condition");
+         goto saw_error;
+       }
+      else if (TREE_CODE (cmp_expr) != GT_EXPR
+              && TREE_CODE (cmp_expr) != LT_EXPR)
+       {
+         error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc),
+                   "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
+                   "condition");
+         goto saw_error;
+       }
+      if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+       goto saw_error;
+
+      extra_scope = true;
+      eloc = cp_lexer_peek_token (parser->lexer)->location;
+      lhs = cp_parser_unary_expression (parser);
+      orig_lhs = lhs;
+      if (lhs == error_mark_node)
+       goto saw_error;
+      if (!cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+       {
+         cp_parser_error (parser, "expected %<=%>");
+         goto saw_error;
+       }
+      cp_lexer_consume_token (parser->lexer);
+      eloc = cp_lexer_peek_token (parser->lexer)->location;
+      if (TREE_CODE (cmp_expr) == EQ_EXPR)
+       rhs1 = cp_parser_expression (parser);
+      else
+       rhs1 = cp_parser_simple_cast_expression (parser);
+
+      if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+       goto saw_error;
+
+      if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE))
+       goto saw_error;
+
+      extra_scope = false;
+      no_semicolon = true;
+
+      if (cp_tree_equal (TREE_OPERAND (cmp_expr, 0), lhs))
+       {
+         if (TREE_CODE (cmp_expr) == EQ_EXPR)
+           {
+             opcode = COND_EXPR;
+             rhs = TREE_OPERAND (cmp_expr, 1);
+           }
+         else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), rhs1))
+           {
+             opcode = (TREE_CODE (cmp_expr) == GT_EXPR
+                       ? MIN_EXPR : MAX_EXPR);
+             rhs = rhs1;
+             rhs1 = TREE_OPERAND (cmp_expr, 0);
+           }
+         else
+           goto bad_if;
+       }
+      else if (TREE_CODE (cmp_expr) == EQ_EXPR)
+       goto bad_if;
+      else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), lhs)
+              && cp_tree_equal (TREE_OPERAND (cmp_expr, 0), rhs1))
+       {
+         opcode = (TREE_CODE (cmp_expr) == GT_EXPR
+                   ? MAX_EXPR : MIN_EXPR);
+         rhs = rhs1;
+         rhs1 = TREE_OPERAND (cmp_expr, 1);
+       }
+      else
+       {
+       bad_if:
+         cp_parser_error (parser,
+                          "invalid form of %<#pragma omp atomic compare%>");
+         goto saw_error;
+       }
+
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+       {
+         if (code != OMP_ATOMIC_CAPTURE_NEW
+             || (structured_block && r == NULL_TREE)
+             || TREE_CODE (cmp_expr) != EQ_EXPR)
+           {
+             eloc = cp_lexer_peek_token (parser->lexer)->location;
+             error_at (eloc, "unexpected %<else%>");
+             goto saw_error;
+           }
+
+         cp_lexer_consume_token (parser->lexer);
+
+         if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+           goto saw_error;
+
+         extra_scope = true;
+         v = cp_parser_unary_expression (parser);
+         if (v == error_mark_node)
+           goto saw_error;
+         if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+           goto saw_error;
+
+         tree expr = cp_parser_simple_cast_expression (parser);
+
+         if (!cp_tree_equal (expr, lhs))
+           goto bad_if;
+
+         if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+           goto saw_error;
+
+         if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE))
+           goto saw_error;
+
+         extra_scope = false;
+         code = OMP_ATOMIC_CAPTURE_OLD;
+         if (r == NULL_TREE)
+           /* Signal to c_finish_omp_atomic that in
+              if (x == e) { x = d; } else { v = x; }
+              case the store to v should be conditional.  */
+           r = void_list_node;
+       }
+      else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       {
+         cp_parser_error (parser, "expected %<else%>");
+         goto saw_error;
+       }
+      else if (code == OMP_ATOMIC_CAPTURE_NEW
+              && r != NULL_TREE
+              && v == NULL_TREE)
+       code = OMP_ATOMIC;
+      goto stmt_done;
+    }
   lhs = cp_parser_unary_expression (parser);
   orig_lhs = lhs;
   switch (TREE_CODE (lhs))
@@ -40094,6 +40401,8 @@ restart:
       lhs = TREE_OPERAND (lhs, 0);
       opcode = PLUS_EXPR;
       rhs = integer_one_node;
+      if (compare)
+       goto invalid_compare;
       break;
 
     case POSTDECREMENT_EXPR:
@@ -40104,6 +40413,8 @@ restart:
       lhs = TREE_OPERAND (lhs, 0);
       opcode = MINUS_EXPR;
       rhs = integer_one_node;
+      if (compare)
+       goto invalid_compare;
       break;
 
     case COMPOUND_EXPR:
@@ -40132,11 +40443,18 @@ restart:
                  && !structured_block
                  && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
                code = OMP_ATOMIC_CAPTURE_OLD;
+             if (compare)
+               goto invalid_compare;
              break;
            }
        }
       /* FALLTHRU */
     default:
+      if (compare && !cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+       {
+         cp_parser_error (parser, "expected %<=%>");
+         goto saw_error;
+       }
       switch (cp_lexer_peek_token (parser->lexer)->type)
        {
        case CPP_MULT_EQ:
@@ -40204,6 +40522,8 @@ restart:
                case BIT_AND_EXPR:
                case BIT_IOR_EXPR:
                case BIT_XOR_EXPR:
+                 if (compare)
+                   break;
                  if (cp_tree_equal (lhs, TREE_OPERAND (rhs, 1)))
                    {
                      if (cp_parser_parse_definitely (parser))
@@ -40217,11 +40537,91 @@ restart:
                        goto saw_error;
                    }
                  break;
+               case EQ_EXPR:
+                 if (!compare
+                     || code != OMP_ATOMIC_CAPTURE_NEW
+                     || !structured_block
+                     || v
+                     || r)
+                   break;
+                 if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+                     && cp_lexer_nth_token_is_keyword (parser->lexer,
+                                                       2, RID_IF))
+                   {
+                     if (cp_parser_parse_definitely (parser))
+                       {
+                         r = lhs;
+                         lhs = NULL_TREE;
+                         rhs1 = NULL_TREE;
+                         cp_lexer_consume_token (parser->lexer);
+                         goto restart;
+                       }
+                   }
+                 break;
+               case GT_EXPR:
+               case LT_EXPR:
+                 if (compare
+                     && cp_lexer_next_token_is (parser->lexer, CPP_QUERY)
+                     && cp_tree_equal (lhs, TREE_OPERAND (rhs, 1))
+                     && cp_parser_parse_definitely (parser))
+                   {
+                     opcode = TREE_CODE (rhs);
+                     rhs1 = TREE_OPERAND (rhs, 0);
+                     rhs = TREE_OPERAND (rhs, 1);
+                    cond_expr:
+                     cp_lexer_consume_token (parser->lexer);
+                     bool saved_colon_corrects_to_scope_p
+                       = parser->colon_corrects_to_scope_p;
+                     parser->colon_corrects_to_scope_p = false;
+                     tree e1 = cp_parser_expression (parser);
+                     parser->colon_corrects_to_scope_p
+                       = saved_colon_corrects_to_scope_p;
+                     cp_parser_require (parser, CPP_COLON, RT_COLON);
+                     tree e2 = cp_parser_simple_cast_expression (parser);
+                     if (cp_tree_equal (lhs, e2))
+                       {
+                         if (cp_tree_equal (lhs, rhs1))
+                           {
+                             if (opcode == EQ_EXPR)
+                               {
+                                 opcode = COND_EXPR;
+                                 rhs1 = e1;
+                                 goto stmt_done;
+                               }
+                             if (cp_tree_equal (rhs, e1))
+                               {
+                                 opcode
+                                   = opcode == GT_EXPR ? MIN_EXPR : MAX_EXPR;
+                                 rhs = e1;
+                                 goto stmt_done;
+                               }
+                           }
+                         else
+                           {
+                             gcc_assert (opcode != EQ_EXPR);
+                             if (cp_tree_equal (rhs1, e1))
+                               {
+                                 opcode
+                                   = opcode == GT_EXPR ? MAX_EXPR : MIN_EXPR;
+                                 rhs1 = rhs;
+                                 rhs = e1;
+                                 goto stmt_done;
+                               }
+                           }
+                       }
+                     cp_parser_error (parser,
+                                      "invalid form of "
+                                      "%<#pragma omp atomic compare%>");
+                     goto saw_error;
+                   }
+                 break;
                default:
                  break;
                }
              cp_parser_abort_tentative_parse (parser);
-             if (structured_block && code == OMP_ATOMIC_CAPTURE_OLD)
+             if (structured_block
+                 && code == OMP_ATOMIC_CAPTURE_OLD
+                 && !compare)
                {
                  rhs = cp_parser_expression (parser);
                  if (rhs == error_mark_node)
@@ -40249,7 +40649,7 @@ restart:
                  cp_lexer_consume_token (parser->lexer);
                  goto restart;
                }
-             else if (structured_block)
+             else if (structured_block && !compare)
                {
                  opcode = NOP_EXPR;
                  rhs = rhs1;
@@ -40286,11 +40686,28 @@ restart:
            case CPP_XOR:
              opcode = BIT_XOR_EXPR;
              break;
+           case CPP_EQ_EQ:
+             opcode = EQ_EXPR;
+             break;
+           case CPP_GREATER:
+             opcode = GT_EXPR;
+             break;
+           case CPP_LESS:
+             opcode = LT_EXPR;
+             break;
            default:
              cp_parser_error (parser,
                               "invalid operator for %<#pragma omp atomic%>");
              goto saw_error;
            }
+         if (compare
+             && TREE_CODE_CLASS (opcode) != tcc_comparison)
+           {
+             cp_parser_error (parser,
+                              "invalid form of "
+                              "%<#pragma omp atomic compare%>");
+             goto saw_error;
+           }
          oprec = TOKEN_PRECEDENCE (token);
          gcc_assert (oprec != PREC_NOT_OPERATOR);
          if (commutative_tree_code (opcode))
@@ -40300,8 +40717,18 @@ restart:
                                             oprec, NULL);
          if (rhs == error_mark_node)
            goto saw_error;
+         if (compare)
+           {
+             if (!cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
+               {
+                 cp_parser_error (parser,
+                                  "invalid form of "
+                                  "%<#pragma omp atomic compare%>");
+                 goto saw_error;
+               }
+             goto cond_expr;
+           }
          goto stmt_done;
-         /* FALLTHROUGH */
        default:
          cp_parser_error (parser,
                           "invalid operator for %<#pragma omp atomic%>");
@@ -40315,10 +40742,12 @@ restart:
       break;
     }
 stmt_done:
-  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
     {
-      if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+      if (!no_semicolon
+         && !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
        goto saw_error;
+      no_semicolon = false;
       v = cp_parser_unary_expression (parser);
       if (v == error_mark_node)
        goto saw_error;
@@ -40330,19 +40759,30 @@ stmt_done:
     }
   if (structured_block)
     {
-      cp_parser_consume_semicolon_at_end_of_statement (parser);
+      if (!no_semicolon)
+       cp_parser_consume_semicolon_at_end_of_statement (parser);
       cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
     }
 done:
+  if (weak && opcode != COND_EXPR)
+    {
+      error_at (loc, "%<weak%> clause requires atomic equality comparison");
+      weak = false;
+    }
   clauses = finish_omp_clauses (clauses, C_ORT_OMP);
   finish_omp_atomic (pragma_tok->location, code, opcode, lhs, rhs, v, lhs1,
-                    rhs1, clauses, memory_order);
-  if (!structured_block)
+                    rhs1, r, clauses, memory_order, weak);
+  if (!structured_block && !no_semicolon)
     cp_parser_consume_semicolon_at_end_of_statement (parser);
   return;
 
+ invalid_compare:
+  error ("invalid form of %<pragma omp atomic compare%>");
+  /* FALLTHRU */
  saw_error:
   cp_parser_skip_to_end_of_block_or_statement (parser);
+  if (extra_scope && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+    cp_lexer_consume_token (parser->lexer);
   if (structured_block)
     {
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
index 9360d6194bd7c088835d62d4f6235704bac7e8d4..a74722de8ba01ffb588a79cadf70e26907d73f4b 100644 (file)
@@ -19049,23 +19049,42 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
        {
          tree op1 = TREE_OPERAND (t, 1);
          tree rhs1 = NULL_TREE;
+         tree r = NULL_TREE;
          tree lhs, rhs;
          if (TREE_CODE (op1) == COMPOUND_EXPR)
            {
              rhs1 = RECUR (TREE_OPERAND (op1, 0));
              op1 = TREE_OPERAND (op1, 1);
            }
-         lhs = RECUR (TREE_OPERAND (op1, 0));
-         rhs = RECUR (TREE_OPERAND (op1, 1));
+         if (TREE_CODE (op1) == COND_EXPR)
+           {
+             gcc_assert (rhs1 == NULL_TREE);
+             tree c = TREE_OPERAND (op1, 0);
+             if (TREE_CODE (c) == MODIFY_EXPR)
+               {
+                 r = RECUR (TREE_OPERAND (c, 0));
+                 c = TREE_OPERAND (c, 1);
+               }
+             gcc_assert (TREE_CODE (c) == EQ_EXPR);
+             rhs = RECUR (TREE_OPERAND (c, 1));
+             lhs = RECUR (TREE_OPERAND (op1, 2));
+             rhs1 = RECUR (TREE_OPERAND (op1, 1));
+           }
+         else
+           {
+             lhs = RECUR (TREE_OPERAND (op1, 0));
+             rhs = RECUR (TREE_OPERAND (op1, 1));
+           }
          finish_omp_atomic (EXPR_LOCATION (t), OMP_ATOMIC, TREE_CODE (op1),
-                            lhs, rhs, NULL_TREE, NULL_TREE, rhs1, tmp,
-                            OMP_ATOMIC_MEMORY_ORDER (t));
+                            lhs, rhs, NULL_TREE, NULL_TREE, rhs1, r,
+                            tmp, OMP_ATOMIC_MEMORY_ORDER (t),
+                            OMP_ATOMIC_WEAK (t));
        }
       else
        {
          tree op1 = TREE_OPERAND (t, 1);
          tree v = NULL_TREE, lhs, rhs = NULL_TREE, lhs1 = NULL_TREE;
-         tree rhs1 = NULL_TREE;
+         tree rhs1 = NULL_TREE, r = NULL_TREE;
          enum tree_code code = TREE_CODE (TREE_OPERAND (op1, 1));
          enum tree_code opcode = NOP_EXPR;
          if (code == OMP_ATOMIC_READ)
@@ -19084,8 +19103,25 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                  rhs1 = RECUR (TREE_OPERAND (op11, 0));
                  op11 = TREE_OPERAND (op11, 1);
                }
-             lhs = RECUR (TREE_OPERAND (op11, 0));
-             rhs = RECUR (TREE_OPERAND (op11, 1));
+             if (TREE_CODE (op11) == COND_EXPR)
+               {
+                 gcc_assert (rhs1 == NULL_TREE);
+                 tree c = TREE_OPERAND (op11, 0);
+                 if (TREE_CODE (c) == MODIFY_EXPR)
+                   {
+                     r = RECUR (TREE_OPERAND (c, 0));
+                     c = TREE_OPERAND (c, 1);
+                   }
+                 gcc_assert (TREE_CODE (c) == EQ_EXPR);
+                 rhs = RECUR (TREE_OPERAND (c, 1));
+                 lhs = RECUR (TREE_OPERAND (op11, 2));
+                 rhs1 = RECUR (TREE_OPERAND (op11, 1));
+               }
+             else
+               {
+                 lhs = RECUR (TREE_OPERAND (op11, 0));
+                 rhs = RECUR (TREE_OPERAND (op11, 1));
+               }
              opcode = TREE_CODE (op11);
              if (opcode == MODIFY_EXPR)
                opcode = NOP_EXPR;
@@ -19097,7 +19133,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
              rhs = RECUR (TREE_OPERAND (op1, 1));
            }
          finish_omp_atomic (EXPR_LOCATION (t), code, opcode, lhs, rhs, v,
-                            lhs1, rhs1, tmp, OMP_ATOMIC_MEMORY_ORDER (t));
+                            lhs1, rhs1, r, tmp,
+                            OMP_ATOMIC_MEMORY_ORDER (t), OMP_ATOMIC_WEAK (t));
        }
       break;
 
index 23eea1b058ce98fdf4c44c344111308597f4eae2..4170621f7fca3f19ef6ac3e8c054898fdf2148b1 100644 (file)
@@ -10493,14 +10493,15 @@ finish_omp_for_block (tree bind, tree omp_for)
 
 void
 finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
-                  tree lhs, tree rhs, tree v, tree lhs1, tree rhs1,
-                  tree clauses, enum omp_memory_order mo)
+                  tree lhs, tree rhs, tree v, tree lhs1, tree rhs1, tree r,
+                  tree clauses, enum omp_memory_order mo, bool weak)
 {
   tree orig_lhs;
   tree orig_rhs;
   tree orig_v;
   tree orig_lhs1;
   tree orig_rhs1;
+  tree orig_r;
   bool dependent_p;
   tree stmt;
 
@@ -10509,6 +10510,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
   orig_v = v;
   orig_lhs1 = lhs1;
   orig_rhs1 = rhs1;
+  orig_r = r;
   dependent_p = false;
   stmt = NULL_TREE;
 
@@ -10520,7 +10522,10 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
                     || (rhs && type_dependent_expression_p (rhs))
                     || (v && type_dependent_expression_p (v))
                     || (lhs1 && type_dependent_expression_p (lhs1))
-                    || (rhs1 && type_dependent_expression_p (rhs1)));
+                    || (rhs1 && type_dependent_expression_p (rhs1))
+                    || (r
+                        && r != void_list_node
+                        && type_dependent_expression_p (r)));
       if (clauses)
        {
          gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE
@@ -10541,17 +10546,19 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
            lhs1 = build_non_dependent_expr (lhs1);
          if (rhs1)
            rhs1 = build_non_dependent_expr (rhs1);
+         if (r && r != void_list_node)
+           r = build_non_dependent_expr (r);
        }
     }
   if (!dependent_p)
     {
       bool swapped = false;
-      if (rhs1 && cp_tree_equal (lhs, rhs))
+      if (rhs1 && opcode != COND_EXPR && cp_tree_equal (lhs, rhs))
        {
          std::swap (rhs, rhs1);
          swapped = !commutative_tree_code (opcode);
        }
-      if (rhs1 && !cp_tree_equal (lhs, rhs1))
+      if (rhs1 && opcode != COND_EXPR && !cp_tree_equal (lhs, rhs1))
        {
          if (code == OMP_ATOMIC)
            error ("%<#pragma omp atomic update%> uses two different "
@@ -10572,7 +10579,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
          return;
        }
       stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs,
-                                 v, lhs1, rhs1, NULL_TREE, swapped, mo, false,
+                                 v, lhs1, rhs1, r, swapped, mo, weak,
                                  processing_template_decl != 0);
       if (stmt == error_mark_node)
        return;
@@ -10589,6 +10596,16 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
        {
          if (opcode == NOP_EXPR)
            stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
+         else if (opcode == COND_EXPR)
+           {
+             stmt = build2 (EQ_EXPR, boolean_type_node, orig_lhs, orig_rhs);
+             if (orig_r)
+               stmt = build2 (MODIFY_EXPR, boolean_type_node, orig_r,
+                              stmt);
+             stmt = build3 (COND_EXPR, void_type_node, stmt, orig_rhs1,
+                            orig_lhs);
+             orig_rhs1 = NULL_TREE;
+           }
          else
            stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
          if (orig_rhs1)
@@ -10598,12 +10615,14 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
            {
              stmt = build_min_nt_loc (loc, code, orig_lhs1, stmt);
              OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
+             OMP_ATOMIC_WEAK (stmt) = weak;
              stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
            }
        }
       stmt = build2 (OMP_ATOMIC, void_type_node,
                     clauses ? clauses : integer_zero_node, stmt);
       OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
+      OMP_ATOMIC_WEAK (stmt) = weak;
       SET_EXPR_LOCATION (stmt, loc);
     }
 
index 17789b4225b381a8cd8accc3f078f200f14e8240..f7e6526bcce51c70aac2bdf0db58f08ef5108e34 100644 (file)
@@ -1,3 +1,29 @@
+2021-09-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-c++-common/gomp/atomic-18.c: Expect same diagnostics in C++ as in
+       C.
+       * c-c++-common/gomp/atomic-25.c: Drop c effective target.
+       * c-c++-common/gomp/atomic-26.c: Likewise.
+       * c-c++-common/gomp/atomic-27.c: Likewise.
+       * c-c++-common/gomp/atomic-28.c: Likewise.
+       * c-c++-common/gomp/atomic-29.c: Likewise.
+       * c-c++-common/gomp/atomic-30.c: Likewise.  Adjust expected diagnostics
+       for C++ when it differs from C.
+       (foo): Change return type from double to void.
+       * g++.dg/gomp/atomic-5.C: Adjust expected diagnostics wording.
+       * g++.dg/gomp/atomic-20.C: New test.
+
+2021-09-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-09-15  Thomas Schwinge  <thomas@codesourcery.com>
+
+       * gfortran.dg/goacc/unexpected-end.f90: Add OpenACC 'host_data'
+       testing.
+
 2021-09-14  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index b389c6a0df8e35b779c1ef4bdf1b9aac652a2c66..a8ed3c7803e8bef4f0ce2ec2e7030d366f500a14 100644 (file)
@@ -12,14 +12,12 @@ foo (int j)
   v = i;
   #pragma omp atomic acquire , write   /* { dg-error "incompatible with 'acquire' clause" } */
   i = v;
-  #pragma omp atomic capture hint (0) capture  /* { dg-error "too many 'capture' clauses" "" { target c } } */
-                                       /* { dg-error "too many atomic clauses" "" { target c++ } .-1 } */
+  #pragma omp atomic capture hint (0) capture  /* { dg-error "too many 'capture' 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', 'compare', 'weak', 'fail', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target c } } */
-                                       /* { dg-error "expected 'read', 'write', 'update', 'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target c++ } .-1 } */
-  i = i + 1;                           /* { dg-error "expected end of line before" "" { target *-*-* } .-2 } */
+  #pragma omp atomic foobar            /* { dg-error "expected 'read', 'write', 'update', 'capture', 'compare', 'weak', 'fail', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" } */
+  i = i + 1;                           /* { dg-error "expected end of line before" "" { target *-*-* } .-1 } */
 }
index a5196a5e305181ac22fd11be5ef0182dc758a3db..653ef187fc86319d987ec8da6ba9f185636e0642 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target c } } */
+/* { dg-do compile } */
 
 int x, r, z;
 double d, v;
index c7e65db09241c135a8d62fe954d99de51204436b..b7a4a1f623806350963585ec9e8e83c8fe81d907 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target c } } */
+/* { dg-do compile } */
 
 int x;
 double d;
index 3d6171740519746f9e54356ee56c767a1da325b7..8f1e7e90000a72d3749bf7b8cd7a2928de30f08b 100644 (file)
@@ -1,5 +1,5 @@
 /* PR middle-end/88968 */
-/* { dg-do compile { target c } } */
+/* { dg-do compile } */
 
 struct __attribute__((packed)) S {
   unsigned int a : 16;
index 50cf22307a6cfb0cd9c68b4e29a9d0e7dae57720..853ae1c1baf7897ffa693c7ee491a50dbb2cdc57 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target c } } */
+/* { dg-do compile } */
 /* { dg-additional-options "-O2 -fdump-tree-ompexp" } */
 /* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 4, 5, 5\\\);" 1 "ompexp" { target sync_int_long } } } */
 /* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 4, 4, 2\\\);" 1 "ompexp" { target sync_int_long } } } */
index 97fe33b392753b12ddd0a35f65a5a2f0b3d073a8..1081e430c38f02ab96b08e191c306cea219f0e8f 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target c } } */
+/* { dg-do compile } */
 /* { dg-additional-options "-O2 -fdump-tree-ompexp" } */
 /* { dg-additional-options "-march=pentium" { target ia32 } } */
 /* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 8, 5, 5\\\);" 1 "ompexp" { target sync_long_long } } } */
index f36de7087798d956bbf1f37b0c6cbd527587104b..37a30bb44bda3039a55e6515cdf4e5c9eab90277 100644 (file)
@@ -1,9 +1,9 @@
-/* { dg-do compile { target c } } */
+/* { dg-do compile } */
 
 int x;
 double d, g;
 
-double
+void
 foo (int y, double e, long double f)
 {
   double v;
@@ -21,18 +21,18 @@ foo (int y, double e, long double f)
   #pragma omp atomic compare
   if (d + e) { d = e; }                /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
   #pragma omp atomic capture compare
-  { r = d >= e; if (r) { d = f; } }    /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
-  #pragma omp atomic capture compare
-  { r = d <= e; if (r) { d = f; } }    /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
-  #pragma omp atomic capture compare
-  { r = d > e; if (r) { d = f; } }     /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
-  #pragma omp atomic capture compare
-  { r = d < e; if (r) { d = f; } }     /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
-  #pragma omp atomic capture compare
-  { r = d != e; if (r) { d = f; } }    /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
-  #pragma omp atomic capture compare
-  { r = d + e; if (r) { d = f; } }     /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
-  #pragma omp atomic capture compare
+  { r = d >= e; if (r) { d = f; } }    /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+  #pragma omp atomic capture compare   /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+  { r = d <= e; if (r) { d = f; } }    /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+  #pragma omp atomic capture compare   /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+  { r = d > e; if (r) { d = f; } }     /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+  #pragma omp atomic capture compare   /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+  { r = d < e; if (r) { d = f; } }     /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+  #pragma omp atomic capture compare   /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+  { r = d != e; if (r) { d = f; } }    /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+  #pragma omp atomic capture compare   /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+  { r = d + e; if (r) { d = f; } }     /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+  #pragma omp atomic capture compare   /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
   { r = d == e; if (r2) { d = f; } }   /* { dg-error "invalid form of '#pragma omp atomic compare' before '\{' token" } */
   #pragma omp atomic capture compare
   if (d > e) { d = e; }                        /* { dg-error "expected '==' comparison in 'if' condition" } */
@@ -97,41 +97,46 @@ foo (int y, double e, long double f)
   #pragma omp atomic compare
   x ^= 5;                              /* { dg-error "expected '=' before '\\\^=' token" } */
   #pragma omp atomic compare
-  x = x + 3;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x - 5;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = 2 * x;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = 5 | x;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x & ~5;                          /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x | 5;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x >= 5 ? 5 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x <= 5 ? 5 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x != 5 ? 7 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = 5 == x ? 7 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x == 5 ? x : 7;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x == 5 ? 9 : 7;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x > 5 ? 6 : x;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x < 5 ? 6 : x;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x > 5 ? x : 6;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic compare
-  x = x < 5 ? x : 6;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
-  #pragma omp atomic capture
+  x = x + 3;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before '\\\+' token" "" { target c++ } .-1 } */
+  x = x - 5;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before '-' token" "" { target c++ } .-1 } */
+  x = 2 * x;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic' before numeric constant" "" { target c++ } .-1 } */
+  x = 5 | x;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic' before numeric constant" "" { target c++ } .-1 } */
+  x = x & ~5;                          /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before '\\\&' token" "" { target c++ } .-1 } */
+  x = x | 5;                           /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before '\\\|' token" "" { target c++ } .-1 } */
+  x = x >= 5 ? 5 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid operator for '#pragma omp atomic' before '>=' token" "" { target c++ } .-1 } */
+  x = x <= 5 ? 5 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid operator for '#pragma omp atomic' before '<=' token" "" { target c++ } .-1 } */
+  x = x != 5 ? 7 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid operator for '#pragma omp atomic' before '!=' token" "" { target c++ } .-1 } */
+  x = 5 == x ? 7 : x;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic' before numeric constant" "" { target c++ } .-1 } */
+  x = x == 5 ? x : 7;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+  x = x == 5 ? 9 : 7;                  /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+  x = x > 5 ? 6 : x;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+  x = x < 5 ? 6 : x;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+  x = x > 5 ? x : 6;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic compare           /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+  x = x < 5 ? x : 6;                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+  #pragma omp atomic capture           /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
   r = x == 5;                          /* { dg-error "invalid operator for '#pragma omp atomic' before '==' token" } */
   #pragma omp atomic capture compare
   r = x == 5;                          /* { dg-error "expected '=' before '==' token" } */
   #pragma omp atomic capture compare   /* { dg-error "'#pragma omp atomic compare capture' with non-integral comparison result" } */
   { v = x == 5; if (v) { x = 6; } }
+  #pragma omp atomic compare capture
+  { r2 = x; x = y; }                   /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
+  #pragma omp atomic compare capture
+  { r2 = x; x = y == 7 ? 12 : y; }     /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+                                       /* { dg-error "invalid form of '#pragma omp atomic' before 'y'" "" { target c++ } .-1 } */
 }
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-20.C b/gcc/testsuite/g++.dg/gomp/atomic-20.C
new file mode 100644 (file)
index 0000000..cb7a37b
--- /dev/null
@@ -0,0 +1,104 @@
+// { dg-do compile }
+
+int x, r, z;
+double d, v;
+long double ld;
+
+template <int N>
+void
+foo (int y, double e, long double f)
+{
+  #pragma omp atomic compare update seq_cst
+  x = x > y ? y : x;
+  #pragma omp atomic compare relaxed
+  d = e > d ? e : d;
+  #pragma omp atomic compare
+  d = f < d ? f : d;
+  #pragma omp atomic compare seq_cst fail(relaxed)
+  x = 12U < x ? 12U : x;
+  #pragma omp atomic compare
+  x = x == 7 ? 24 : x;
+  #pragma omp atomic compare
+  x = x == 123UL ? 256LL : x;
+  #pragma omp atomic compare
+  ld = ld == f ? f + 5.0L : ld;
+  #pragma omp atomic compare
+  if (x == 9) { x = 5; }
+  #pragma omp atomic compare
+  if (x > 5) { x = 5; }
+  #pragma omp atomic compare
+  if (7 > x) { x = 7; }
+  #pragma omp atomic compare update capture seq_cst fail(acquire)
+  v = d = f > d ? f : d;
+  #pragma omp atomic update capture compare
+  v = x = x < 24ULL ? 24ULL : x;
+  #pragma omp atomic compare, capture, update
+  v = x = x == e ? f : x;
+  #pragma omp atomic capture compare
+  { v = d; if (d > e) { d = e; } }
+  #pragma omp atomic compare capture
+  { if (e < d) { d = e; } v = d; }
+  #pragma omp atomic compare capture
+  { y = x; if (x == 42) { x = 7; } }
+  #pragma omp atomic capture compare weak
+  { if (x == 42) { x = 7; } y = x; }
+  #pragma omp atomic capture compare fail(seq_cst)
+  if (d == 8.0) { d = 16.0; } else { v = d; }
+  #pragma omp atomic capture compare
+  { r = x == 8; if (r) { x = 24; } }
+  #pragma omp atomic compare capture
+  { r = x == y; if (r) { x = y + 6; } else { z = x; } }
+}
+
+template <typename I, typename D, typename LD>
+void
+bar (I &x, I &r, I &z, D &d, D &v, LD &ld, I y, D e, LD f)
+{
+  #pragma omp atomic compare update seq_cst
+  x = x > y ? y : x;
+  #pragma omp atomic compare relaxed
+  d = e > d ? e : d;
+  #pragma omp atomic compare
+  d = f < d ? f : d;
+  #pragma omp atomic compare seq_cst fail(relaxed)
+  x = 12U < x ? 12U : x;
+  #pragma omp atomic compare
+  x = x == 7 ? 24 : x;
+  #pragma omp atomic compare
+  x = x == 123UL ? 256LL : x;
+  #pragma omp atomic compare
+  ld = ld == f ? f + 5.0L : ld;
+  #pragma omp atomic compare
+  if (x == 9) { x = 5; }
+  #pragma omp atomic compare
+  if (x > 5) { x = 5; }
+  #pragma omp atomic compare
+  if (7 > x) { x = 7; }
+  #pragma omp atomic compare update capture seq_cst fail(acquire)
+  v = d = f > d ? f : d;
+  #pragma omp atomic update capture compare
+  v = x = x < 24ULL ? 24ULL : x;
+  #pragma omp atomic compare, capture, update
+  v = x = x == e ? f : x;
+  #pragma omp atomic capture compare
+  { v = d; if (d > e) { d = e; } }
+  #pragma omp atomic compare capture
+  { if (e < d) { d = e; } v = d; }
+  #pragma omp atomic compare capture
+  { y = x; if (x == 42) { x = 7; } }
+  #pragma omp atomic capture compare weak
+  { if (x == 42) { x = 7; } y = x; }
+  #pragma omp atomic capture compare fail(seq_cst)
+  if (d == 8.0) { d = 16.0; } else { v = d; }
+  #pragma omp atomic capture compare
+  { r = x == 8; if (r) { x = 24; } }
+  #pragma omp atomic compare capture
+  { r = x == y; if (r) { x = y + 6; } else { z = x; } }
+}
+
+void
+baz (int y, double e, long double f)
+{
+  foo <0> (y, e, f);
+  bar (x, r, z, d, v, ld, y, e, f);
+}
index 78f6344361be0ad7378442cc383959f06c131c49..e2fd5915cf7edc254416530e49cb8c1ab0572f4f 100644 (file)
@@ -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++;               /* { dg-error "expected 'read', 'write', 'update', 'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target *-*-* } .-1 } */
+    x++;               /* { dg-error "expected 'read', 'write', 'update', 'capture', 'compare', 'weak', 'fail', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target *-*-* } .-1 } */
   #pragma omp atomic
     ;                  /* { dg-error "expected primary-expression" } */
   #pragma omp atomic
index 250b29b4f8adc875265354779e55226c14b5efbd..09d54f2816a1cb7a3fe149f1a2af1263f82c0fad 100644 (file)
@@ -1,3 +1,15 @@
+2021-09-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * testsuite/libgomp.c-c++-common/atomic-19.c: Drop c effective target.
+       Use /* */ comments instead of //.
+       * testsuite/libgomp.c-c++-common/atomic-20.c: Likewise.
+       * testsuite/libgomp.c-c++-common/atomic-21.c: Likewise.
+       * testsuite/libgomp.c++/atomic-16.C: New test.
+       * testsuite/libgomp.c++/atomic-17.C: New test.
+
 2021-09-13  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
diff --git a/libgomp/testsuite/libgomp.c++/atomic-16.C b/libgomp/testsuite/libgomp.c++/atomic-16.C
new file mode 100644 (file)
index 0000000..1bbd48a
--- /dev/null
@@ -0,0 +1,538 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+int x = 6;
+int w, y;
+
+int *
+foo (void)
+{
+  if (w)
+    abort ();
+  return &y;
+}
+
+template <int N>
+void
+bar ()
+{
+  int v, r;
+  #pragma omp atomic compare
+  x = x > 8 ? 8 : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic compare
+  x = x > 4 ? 4 : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 4)
+    abort ();
+  #pragma omp atomic compare capture
+  v = x = x < 8 ? 8 : x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 12 ? 12 : x; }
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 4 ? 4 : x; }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic write
+  x = -32;
+  #pragma omp atomic capture compare seq_cst fail(relaxed)
+  { x = 12U < x ? 12U : x; v = x; }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic compare
+  x = x == 12 ? 16 : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  r = 57;
+  #pragma omp atomic compare capture
+  v = x = x == 15 ? r + 7 : x;
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; x = x == 73ULL - r ? 12LL : x; }
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { x = x == 69LL - r ? (unsigned char) 6 : x; v = x; }
+  if (v != 6)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 8) { x = 8; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 4) { x = 4; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 4)
+    abort ();
+  #pragma omp atomic compare capture
+  { if (x < 8) { x = 8; } v = x; }
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 12) { x = 12; } }
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 4) { x = 4; } }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic write
+  x = -32;
+  #pragma omp atomic capture compare seq_cst fail(relaxed)
+  { if (12U < x) { x = 12U; } v = x; }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic compare
+  if (x == 12) { x = 16; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  r = 57;
+  #pragma omp atomic compare capture
+  { if (x == 15) { x = r + 7; } v = x; }
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; if (x == 73ULL - r) { x = 12LL; } }
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { if (x == 69LL - r) { x = (unsigned char) 6; } v = x; }
+  if (v != 6)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = 24;
+  #pragma omp atomic compare capture
+  if (x == 12) { x = 16; } else { v = x; }
+  if (v != 6)
+    abort ();
+  v = 32;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = 147;
+  #pragma omp atomic capture compare
+  if (x == 6) { x = 57; } else { v = x; }
+  if (v != 147)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57)
+    abort ();
+  #pragma omp atomic update, capture, compare, weak, seq_cst, fail (relaxed)
+  { r = x == 137; if (r) { x = 174; } }
+  if (r)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57)
+    abort ();
+  #pragma omp atomic compare capture fail (relaxed)
+  { r = x == 57; if (r) { x = 6; } }
+  if (r != 1)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = -5;
+  #pragma omp atomic capture compare
+  { r = x == 17; if (r) { x = 25; } else { v = x; } }
+  if (r || v != 6)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = 15;
+  #pragma omp atomic capture compare
+  { r = x == 6; if (r) { x = 23; } else { v = x; } }
+  if (r != 1 || v != 15)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+  w = 1;
+  #pragma omp atomic compare capture
+  if (x == 23) { x = 57; } else { foo ()[0] = x; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 57)
+    abort ();
+  #pragma omp atomic capture update compare
+  { r = x == 57; if (r) { x = 23; } else { foo ()[0] = x; } }
+  if (r != 1)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+  w = 0;
+  #pragma omp atomic compare capture
+  if (x == 24) { x = 57; } else { foo ()[0] = x; }
+  if (y != 23)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+  y = -5;
+  #pragma omp atomic capture update compare
+  {
+    r = x == 57;
+    if (r)
+      {
+       x = 27;
+      }
+    else
+      {
+       foo ()[0] = x;
+      }
+  }
+  if (r || y != 23)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+}
+
+template <typename T>
+void
+baz (T &x, T &w, T &y)
+{
+  T v, r;
+  #pragma omp atomic compare
+  x = x > 8 ? 8 : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic compare
+  x = x > 4 ? 4 : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 4)
+    abort ();
+  #pragma omp atomic compare capture
+  v = x = x < 8 ? 8 : x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 12 ? 12 : x; }
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 4 ? 4 : x; }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic write
+  x = -32;
+  #pragma omp atomic capture compare seq_cst fail(relaxed)
+  { x = 12U < x ? 12U : x; v = x; }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic compare
+  x = x == 12 ? 16 : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  r = 57;
+  #pragma omp atomic compare capture
+  v = x = x == 15 ? r + 7 : x;
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; x = x == 73ULL - r ? 12LL : x; }
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { x = x == 69LL - r ? (unsigned char) 6 : x; v = x; }
+  if (v != 6)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 8) { x = 8; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 4) { x = 4; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 4)
+    abort ();
+  #pragma omp atomic compare capture
+  { if (x < 8) { x = 8; } v = x; }
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 12) { x = 12; } }
+  if (v != 8)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 4) { x = 4; } }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic write
+  x = -32;
+  #pragma omp atomic capture compare seq_cst fail(relaxed)
+  { if (12U < x) { x = 12U; } v = x; }
+  if (v != 12)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic compare
+  if (x == 12) { x = 16; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  r = 57;
+  #pragma omp atomic compare capture
+  { if (x == 15) { x = r + 7; } v = x; }
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; if (x == 73ULL - r) { x = 12LL; } }
+  if (v != 16)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { if (x == 69LL - r) { x = (unsigned char) 6; } v = x; }
+  if (v != 6)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = 24;
+  #pragma omp atomic compare capture
+  if (x == 12) { x = 16; } else { v = x; }
+  if (v != 6)
+    abort ();
+  v = 32;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = 147;
+  #pragma omp atomic capture compare
+  if (x == 6) { x = 57; } else { v = x; }
+  if (v != 147)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57)
+    abort ();
+  #pragma omp atomic update, capture, compare, weak, seq_cst, fail (relaxed)
+  { r = x == 137; if (r) { x = 174; } }
+  if (r)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57)
+    abort ();
+  #pragma omp atomic compare capture fail (relaxed)
+  { r = x == 57; if (r) { x = 6; } }
+  if (r != 1)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = -5;
+  #pragma omp atomic capture compare
+  { r = x == 17; if (r) { x = 25; } else { v = x; } }
+  if (r || v != 6)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6)
+    abort ();
+  v = 15;
+  #pragma omp atomic capture compare
+  { r = x == 6; if (r) { x = 23; } else { v = x; } }
+  if (r != 1 || v != 15)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+  w = 1;
+  #pragma omp atomic compare capture
+  if (x == 23) { x = 57; } else { foo ()[0] = x; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 57)
+    abort ();
+  #pragma omp atomic capture update compare
+  { r = x == 57; if (r) { x = 23; } else { foo ()[0] = x; } }
+  if (r != 1)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+  w = 0;
+  #pragma omp atomic compare capture
+  if (x == 24) { x = 57; } else { foo ()[0] = x; }
+  if (y != 23)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+  y = -5;
+  #pragma omp atomic capture update compare
+  {
+    r = x == 57;
+    if (r)
+      {
+       x = 27;
+      }
+    else
+      {
+       foo ()[0] = x;
+      }
+  }
+  if (r || y != 23)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23)
+    abort ();
+}
+
+int
+main ()
+{
+  bar <0> ();
+  #pragma omp atomic write
+  x = 6;
+  y = 0;
+  w = 0;
+  baz (x, w, y);
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-17.C b/libgomp/testsuite/libgomp.c++/atomic-17.C
new file mode 100644 (file)
index 0000000..68ae7fc
--- /dev/null
@@ -0,0 +1,407 @@
+// { dg-do run }
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+float x = 6.0f;
+
+template <int N>
+void
+bar ()
+{
+  float v;
+  int r;
+  #pragma omp atomic compare
+  x = x > 8.0f ? 8.0f : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic compare
+  x = x > 4.0f ? 4.0f : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 4.0f)
+    abort ();
+  #pragma omp atomic compare capture
+  v = x = x < 8.0f ? 8.0f : x;
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 12.0f ? 12.0f : x; }
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 4.0f ? 4.0f : x; }
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic compare
+  x = x == 12.0 ? 16.0L : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0)
+    abort ();
+  r = 57;
+  #pragma omp atomic compare capture
+  v = x = x == 15.0f ? r + 7.0f : x;
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; x = x == 73.0L - r ? 12.0f : x; }
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { x = x == 69.0 - r ? 6.0f : x; v = x; }
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 8.0f) { x = 8.0f; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 4.0) { x = 4.0; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 4.0f)
+    abort ();
+  #pragma omp atomic compare capture
+  { if (x < 8.0f) { x = 8.0f; } v = x; }
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 12.0f) { x = 12.0f; } }
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 4.0L) { x = 4.0L; } }
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic compare
+  if (x == 12.0f) { x = 16.0L; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0f)
+    abort ();
+  r = 57.0;
+  #pragma omp atomic compare capture
+  { if (x == 15.0f) { x = r + 7.0f; } v = x; }
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; if (x == 73.0L - r) { x = 12.0L; } }
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { if (x == 69.0L - r) { x = 6.0; } v = x; }
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = 24;
+  #pragma omp atomic compare capture
+  if (x == 12.0f) { x = 16.0f; } else { v = x; }
+  if (v != 6.0f)
+    abort ();
+  v = 32.0f;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = 147.0f;
+  #pragma omp atomic capture compare
+  if (x == 6.0f) { x = 57.0f; } else { v = x; }
+  if (v != 147.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57.0f)
+    abort ();
+  #pragma omp atomic update, capture, compare, weak, seq_cst, fail (relaxed)
+  { r = x == 137.0f; if (r) { x = 174.0f; } }
+  if (r)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57.0f)
+    abort ();
+  #pragma omp atomic compare capture fail (relaxed)
+  { r = x == 57.0f; if (r) { x = 6.0f; } }
+  if (r != 1)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = -5.0f;
+  #pragma omp atomic capture compare
+  { r = x == 17.0L; if (r) { x = 25.0; } else { v = x; } }
+  if (r || v != 6.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = 15.0f;
+  #pragma omp atomic capture compare
+  { r = x == 6.0f; if (r) { x = 23.0f; } else { v = x; } }
+  if (r != 1 || v != 15.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23.0f)
+    abort ();
+}
+
+template <typename T, typename U>
+void
+baz (T &x)
+{
+  T v;
+  U r;
+  #pragma omp atomic compare
+  x = x > 8.0f ? 8.0f : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic compare
+  x = x > 4.0f ? 4.0f : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 4.0f)
+    abort ();
+  #pragma omp atomic compare capture
+  v = x = x < 8.0f ? 8.0f : x;
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 12.0f ? 12.0f : x; }
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; x = x < 4.0f ? 4.0f : x; }
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic compare
+  x = x == 12.0 ? 16.0L : x;
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0)
+    abort ();
+  r = 57;
+  #pragma omp atomic compare capture
+  v = x = x == 15.0f ? r + 7.0f : x;
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; x = x == 73.0L - r ? 12.0f : x; }
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { x = x == 69.0 - r ? 6.0f : x; v = x; }
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 8.0f) { x = 8.0f; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic compare
+  if (x > 4.0) { x = 4.0; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 4.0f)
+    abort ();
+  #pragma omp atomic compare capture
+  { if (x < 8.0f) { x = 8.0f; } v = x; }
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 12.0f) { x = 12.0f; } }
+  if (v != 8.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic capture compare
+  { v = x; if (x < 4.0L) { x = 4.0L; } }
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic compare
+  if (x == 12.0f) { x = 16.0L; }
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0f)
+    abort ();
+  r = 57.0;
+  #pragma omp atomic compare capture
+  { if (x == 15.0f) { x = r + 7.0f; } v = x; }
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic capture, update, compare seq_cst fail(acquire)
+  { v = x; if (x == 73.0L - r) { x = 12.0L; } }
+  if (v != 16.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 12.0f)
+    abort ();
+  #pragma omp atomic update, compare, capture
+  { if (x == 69.0L - r) { x = 6.0; } v = x; }
+  if (v != 6.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = 24;
+  #pragma omp atomic compare capture
+  if (x == 12.0f) { x = 16.0f; } else { v = x; }
+  if (v != 6.0f)
+    abort ();
+  v = 32.0f;
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = 147.0f;
+  #pragma omp atomic capture compare
+  if (x == 6.0f) { x = 57.0f; } else { v = x; }
+  if (v != 147.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57.0f)
+    abort ();
+  #pragma omp atomic update, capture, compare, weak, seq_cst, fail (relaxed)
+  { r = x == 137.0f; if (r) { x = 174.0f; } }
+  if (r)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 57.0f)
+    abort ();
+  #pragma omp atomic compare capture fail (relaxed)
+  { r = x == 57.0f; if (r) { x = 6.0f; } }
+  if (r != 1)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = -5.0f;
+  #pragma omp atomic capture compare
+  { r = x == 17.0L; if (r) { x = 25.0; } else { v = x; } }
+  if (r || v != 6.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 6.0f)
+    abort ();
+  v = 15.0f;
+  #pragma omp atomic capture compare
+  { r = x == 6.0f; if (r) { x = 23.0f; } else { v = x; } }
+  if (r != 1 || v != 15.0f)
+    abort ();
+  #pragma omp atomic read
+  v = x;
+  if (v != 23.0f)
+    abort ();
+}
+
+int
+main ()
+{
+  bar <0> ();
+  #pragma omp atomic write
+  x = 6.0f;
+  baz <float, int> (x);
+}
index 3aee228a20ecd06d9789be5f07f85825605d1203..0437983d35bade2cb886001d2736214016ed42dd 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do run { target c } }
+/* { dg-do run } */
 
 extern
 #ifdef __cplusplus
index 571a714238dc7eb19d1a025598e9049dbb1ee2b7..245d7167fbb28c746aee0b2c09370f8d68d58a64 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do run { target c } }
+/* { dg-do run } */
 
 extern
 #ifdef __cplusplus
index 87216e24925d5aa49f9f1434f889722ad6692e6d..8f66c429a544e21962b67fe8bf78e55bb2840d74 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do run { target c } }
+/* { dg-do run } */
 
 double d;
 long double ld;