From 3a2bcffac602f5de56537a77db1062984bcefd45 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 17 Sep 2021 11:28:31 +0200 Subject: [PATCH] openmp: Add support for OpenMP 5.1 atomics for C++ 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 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. --- gcc/c-family/c-omp.c | 28 +- gcc/c/c-parser.c | 2 +- gcc/cp/cp-tree.h | 4 +- gcc/cp/parser.c | 466 ++++++++++++++- gcc/cp/pt.c | 53 +- gcc/cp/semantics.c | 31 +- gcc/testsuite/c-c++-common/gomp/atomic-18.c | 8 +- gcc/testsuite/c-c++-common/gomp/atomic-25.c | 2 +- gcc/testsuite/c-c++-common/gomp/atomic-26.c | 2 +- gcc/testsuite/c-c++-common/gomp/atomic-27.c | 2 +- gcc/testsuite/c-c++-common/gomp/atomic-28.c | 2 +- gcc/testsuite/c-c++-common/gomp/atomic-29.c | 2 +- gcc/testsuite/c-c++-common/gomp/atomic-30.c | 97 ++-- gcc/testsuite/g++.dg/gomp/atomic-20.C | 104 ++++ gcc/testsuite/g++.dg/gomp/atomic-5.C | 2 +- libgomp/testsuite/libgomp.c++/atomic-16.C | 538 ++++++++++++++++++ libgomp/testsuite/libgomp.c++/atomic-17.C | 407 +++++++++++++ .../libgomp.c-c++-common/atomic-19.c | 2 +- .../libgomp.c-c++-common/atomic-20.c | 2 +- .../libgomp.c-c++-common/atomic-21.c | 2 +- 20 files changed, 1652 insertions(+), 104 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/atomic-20.C create mode 100644 libgomp/testsuite/libgomp.c++/atomic-16.C create mode 100644 libgomp/testsuite/libgomp.c++/atomic-17.C diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 75184a36238..476abc124b2 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -376,7 +376,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) @@ -443,12 +443,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, @@ -529,14 +531,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 @@ -545,10 +544,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; diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index d82c042cfda..eba9bbf5ec7 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -18500,7 +18500,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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e5f632afba4..fb0d5ec5efe 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7582,8 +7582,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, diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8d60f40706b..20f949edfe0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -40082,19 +40082,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)) { @@ -40114,6 +40151,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; @@ -40121,7 +40162,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) { @@ -40129,6 +40170,52 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) error_at (cloc, "expected %, %, %, " "or % 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 %, % " + "or %"); + 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")) @@ -40149,8 +40236,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) { p = NULL; error_at (cloc, "expected %, %, %, " - "%, %, %, " - "%, % or % clause"); + "%, %, %, %, " + "%, %, %, " + "% or % clause"); } if (p) { @@ -40173,6 +40261,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; } @@ -40183,6 +40292,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 % or % " + "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 % or % " + "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) @@ -40244,6 +40377,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) { @@ -40276,6 +40413,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); @@ -40283,12 +40423,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 % 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 % " + "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 %"); + 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 %"); + 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)) @@ -40304,6 +40611,8 @@ restart: lhs = TREE_OPERAND (lhs, 0); opcode = PLUS_EXPR; rhs = integer_one_node; + if (compare) + goto invalid_compare; break; case POSTDECREMENT_EXPR: @@ -40314,6 +40623,8 @@ restart: lhs = TREE_OPERAND (lhs, 0); opcode = MINUS_EXPR; rhs = integer_one_node; + if (compare) + goto invalid_compare; break; case COMPOUND_EXPR: @@ -40342,11 +40653,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: @@ -40414,6 +40732,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)) @@ -40427,11 +40747,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) @@ -40459,7 +40859,7 @@ restart: cp_lexer_consume_token (parser->lexer); goto restart; } - else if (structured_block) + else if (structured_block && !compare) { opcode = NOP_EXPR; rhs = rhs1; @@ -40496,11 +40896,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)) @@ -40510,8 +40927,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%>"); @@ -40525,10 +40952,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; @@ -40540,19 +40969,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, "% 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 %"); + /* 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)) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 22c74da7935..12c8812d8b2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -19030,23 +19030,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) @@ -19065,8 +19084,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; @@ -19078,7 +19114,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; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 94e6b181d5d..35a7b9f7b83 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -9877,14 +9877,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; @@ -9893,6 +9894,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; @@ -9904,7 +9906,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 @@ -9925,17 +9930,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 " @@ -9956,7 +9963,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; @@ -9973,6 +9980,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) @@ -9982,12 +9999,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); } diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-18.c b/gcc/testsuite/c-c++-common/gomp/atomic-18.c index b389c6a0df8..a8ed3c7803e 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-18.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-18.c @@ -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 } */ } diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-25.c b/gcc/testsuite/c-c++-common/gomp/atomic-25.c index a5196a5e305..653ef187fc8 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-25.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-25.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target c } } */ +/* { dg-do compile } */ int x, r, z; double d, v; diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-26.c b/gcc/testsuite/c-c++-common/gomp/atomic-26.c index c7e65db0924..b7a4a1f6238 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-26.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-26.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target c } } */ +/* { dg-do compile } */ int x; double d; diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-27.c b/gcc/testsuite/c-c++-common/gomp/atomic-27.c index 3d617174051..8f1e7e90000 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-27.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-27.c @@ -1,5 +1,5 @@ /* PR middle-end/88968 */ -/* { dg-do compile { target c } } */ +/* { dg-do compile } */ struct __attribute__((packed)) S { unsigned int a : 16; diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-28.c b/gcc/testsuite/c-c++-common/gomp/atomic-28.c index 50cf22307a6..853ae1c1baf 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-28.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-28.c @@ -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 } } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-29.c b/gcc/testsuite/c-c++-common/gomp/atomic-29.c index 97fe33b3927..1081e430c38 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-29.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-29.c @@ -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 } } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-30.c b/gcc/testsuite/c-c++-common/gomp/atomic-30.c index f36de708779..37a30bb44bd 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-30.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-30.c @@ -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 index 00000000000..cb7a37ba83e --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/atomic-20.C @@ -0,0 +1,104 @@ +// { dg-do compile } + +int x, r, z; +double d, v; +long double ld; + +template +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 +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); +} diff --git a/gcc/testsuite/g++.dg/gomp/atomic-5.C b/gcc/testsuite/g++.dg/gomp/atomic-5.C index 78f6344361b..e2fd5915cf7 100644 --- a/gcc/testsuite/g++.dg/gomp/atomic-5.C +++ b/gcc/testsuite/g++.dg/gomp/atomic-5.C @@ -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 diff --git a/libgomp/testsuite/libgomp.c++/atomic-16.C b/libgomp/testsuite/libgomp.c++/atomic-16.C new file mode 100644 index 00000000000..1bbd48a5ff8 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/atomic-16.C @@ -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 +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 +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 index 00000000000..68ae7fc30ab --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/atomic-17.C @@ -0,0 +1,407 @@ +// { dg-do run } + +extern +#ifdef __cplusplus +"C" +#endif +void abort (void); +float x = 6.0f; + +template +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 +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 (x); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/atomic-19.c b/libgomp/testsuite/libgomp.c-c++-common/atomic-19.c index 3aee228a20e..0437983d35b 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/atomic-19.c +++ b/libgomp/testsuite/libgomp.c-c++-common/atomic-19.c @@ -1,4 +1,4 @@ -// { dg-do run { target c } } +/* { dg-do run } */ extern #ifdef __cplusplus diff --git a/libgomp/testsuite/libgomp.c-c++-common/atomic-20.c b/libgomp/testsuite/libgomp.c-c++-common/atomic-20.c index 571a714238d..245d7167fbb 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/atomic-20.c +++ b/libgomp/testsuite/libgomp.c-c++-common/atomic-20.c @@ -1,4 +1,4 @@ -// { dg-do run { target c } } +/* { dg-do run } */ extern #ifdef __cplusplus diff --git a/libgomp/testsuite/libgomp.c-c++-common/atomic-21.c b/libgomp/testsuite/libgomp.c-c++-common/atomic-21.c index 87216e24925..8f66c429a54 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/atomic-21.c +++ b/libgomp/testsuite/libgomp.c-c++-common/atomic-21.c @@ -1,4 +1,4 @@ -// { dg-do run { target c } } +/* { dg-do run } */ double d; long double ld;