From patchwork Fri Sep 17 09:31:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 45115 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 29B62385841C for ; Fri, 17 Sep 2021 09:34:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 29B62385841C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1631871251; bh=jKlz3bXVbvgGgBFLwYFT0Qn0NRiNe+7esb4tj3SRli4=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=ak+JM4iX40qNFSIr2sB9E+1VWk/TbdtpXRhY0qf4PTm8AUVz0zGk5Zb0p29ERbVhy D1Rr9Nha1YCUQ2TXsUdsSUW+VSdFHnOl0dfgTXNsyM3AvbAA0XxTDNNnz0sUeeFBNb xXKczMta95BiWODDWS1v6OELtO91fwPhi57zUtVo= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id D921A3858004 for ; Fri, 17 Sep 2021 09:32:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D921A3858004 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-155-by58kyLfO26t2uYyJUQSDA-1; Fri, 17 Sep 2021 05:32:01 -0400 X-MC-Unique: by58kyLfO26t2uYyJUQSDA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7D731108468A; Fri, 17 Sep 2021 09:32:00 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.34]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A36C82C00F; Fri, 17 Sep 2021 09:31:59 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 18H9VuFs1512733 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 17 Sep 2021 11:31:57 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 18H9Vu2A1512732; Fri, 17 Sep 2021 11:31:56 +0200 Date: Fri, 17 Sep 2021 11:31:55 +0200 To: gcc-patches@gcc.gnu.org Subject: [committed] openmp: Add support for OpenMP 5.1 atomics for C++ Message-ID: <20210917093155.GM304296@tucnak> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: Tobias Burnus Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi! 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. Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 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. Jakub --- gcc/c-family/c-omp.c.jj 2021-09-11 09:33:37.735334112 +0200 +++ gcc/c-family/c-omp.c 2021-09-16 19:20:21.349157878 +0200 @@ -376,7 +376,7 @@ c_finish_omp_atomic (location_t loc, enu 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, enu } } } - 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, enu } } 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, enu 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; --- gcc/c/c-parser.c.jj 2021-09-11 09:33:37.738334069 +0200 +++ gcc/c/c-parser.c 2021-09-16 18:18:30.366878199 +0200 @@ -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); --- gcc/cp/cp-tree.h.jj 2021-09-16 10:51:02.248976859 +0200 +++ gcc/cp/cp-tree.h 2021-09-16 12:23:59.870529826 +0200 @@ -7582,8 +7582,8 @@ extern tree finish_omp_for (location_t 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, --- gcc/cp/parser.c.jj 2021-09-16 10:51:02.273976517 +0200 +++ gcc/cp/parser.c 2021-09-16 18:26:31.540298668 +0200 @@ -40082,19 +40082,56 @@ cp_parser_omp_allocate (cp_parser *parse 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, 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, 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, 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, { p = NULL; error_at (cloc, "expected %, %, %, " - "%, %, %, " - "%, % or % clause"); + "%, %, %, %, " + "%, %, %, " + "% or % clause"); } if (p) { @@ -40173,6 +40261,27 @@ cp_parser_omp_atomic (cp_parser *parser, 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, 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, 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_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, 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)) --- gcc/cp/semantics.c.jj 2021-09-16 10:50:56.484055828 +0200 +++ gcc/cp/semantics.c 2021-09-16 18:42:20.907320083 +0200 @@ -9877,14 +9877,15 @@ finish_omp_for_block (tree bind, tree om 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 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 || (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 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 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 { 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 { 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); } --- gcc/cp/pt.c.jj 2021-09-16 10:50:56.457056198 +0200 +++ gcc/cp/pt.c 2021-09-16 19:41:51.149525562 +0200 @@ -19029,23 +19029,42 @@ tsubst_expr (tree t, tree args, tsubst_f { 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) @@ -19064,8 +19083,25 @@ tsubst_expr (tree t, tree args, tsubst_f 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; @@ -19077,7 +19113,8 @@ tsubst_expr (tree t, tree args, tsubst_f 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; --- gcc/testsuite/c-c++-common/gomp/atomic-18.c.jj 2021-09-11 09:33:37.897331795 +0200 +++ gcc/testsuite/c-c++-common/gomp/atomic-18.c 2021-09-16 15:52:08.356939366 +0200 @@ -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 } */ } --- gcc/testsuite/c-c++-common/gomp/atomic-25.c.jj 2021-09-11 09:33:37.897331795 +0200 +++ gcc/testsuite/c-c++-common/gomp/atomic-25.c 2021-09-16 15:33:53.255895978 +0200 @@ -1,4 +1,4 @@ -/* { dg-do compile { target c } } */ +/* { dg-do compile } */ int x, r, z; double d, v; --- gcc/testsuite/c-c++-common/gomp/atomic-26.c.jj 2021-09-11 09:33:37.897331795 +0200 +++ gcc/testsuite/c-c++-common/gomp/atomic-26.c 2021-09-16 15:34:07.144706331 +0200 @@ -1,4 +1,4 @@ -/* { dg-do compile { target c } } */ +/* { dg-do compile } */ int x; double d; --- gcc/testsuite/c-c++-common/gomp/atomic-27.c.jj 2021-09-11 09:33:37.897331795 +0200 +++ gcc/testsuite/c-c++-common/gomp/atomic-27.c 2021-09-16 15:34:19.308540236 +0200 @@ -1,5 +1,5 @@ /* PR middle-end/88968 */ -/* { dg-do compile { target c } } */ +/* { dg-do compile } */ struct __attribute__((packed)) S { unsigned int a : 16; --- gcc/testsuite/c-c++-common/gomp/atomic-28.c.jj 2021-09-11 09:33:37.897331795 +0200 +++ gcc/testsuite/c-c++-common/gomp/atomic-28.c 2021-09-16 15:34:36.236309092 +0200 @@ -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 } } } */ --- gcc/testsuite/c-c++-common/gomp/atomic-29.c.jj 2021-09-14 10:38:14.803078617 +0200 +++ gcc/testsuite/c-c++-common/gomp/atomic-29.c 2021-09-16 15:34:45.063188563 +0200 @@ -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 } } } */ --- gcc/testsuite/c-c++-common/gomp/atomic-30.c.jj 2021-09-11 09:33:37.897331795 +0200 +++ gcc/testsuite/c-c++-common/gomp/atomic-30.c 2021-09-16 18:32:16.508581686 +0200 @@ -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 } */ } --- gcc/testsuite/g++.dg/gomp/atomic-5.C.jj 2020-01-12 11:54:37.176401897 +0100 +++ gcc/testsuite/g++.dg/gomp/atomic-5.C 2021-09-16 17:02:56.352894724 +0200 @@ -23,7 +23,7 @@ void f1(void) #pragma omp atomic bar() += 1; /* { dg-error "lvalue required" } */ #pragma omp atomic a /* { dg-error "expected end of line" } */ - x++; /* { 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 --- gcc/testsuite/g++.dg/gomp/atomic-20.C.jj 2021-09-16 19:01:44.401425349 +0200 +++ gcc/testsuite/g++.dg/gomp/atomic-20.C 2021-09-16 19:57:33.238645854 +0200 @@ -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); +} --- libgomp/testsuite/libgomp.c-c++-common/atomic-19.c.jj 2021-09-11 09:33:37.964330837 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/atomic-19.c 2021-09-16 20:07:22.807584290 +0200 @@ -1,4 +1,4 @@ -// { dg-do run { target c } } +/* { dg-do run } */ extern #ifdef __cplusplus --- libgomp/testsuite/libgomp.c-c++-common/atomic-20.c.jj 2021-09-11 09:33:37.964330837 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/atomic-20.c 2021-09-16 20:07:30.911473447 +0200 @@ -1,4 +1,4 @@ -// { dg-do run { target c } } +/* { dg-do run } */ extern #ifdef __cplusplus --- libgomp/testsuite/libgomp.c-c++-common/atomic-21.c.jj 2021-09-11 09:33:37.964330837 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/atomic-21.c 2021-09-16 20:07:36.606395557 +0200 @@ -1,4 +1,4 @@ -// { dg-do run { target c } } +/* { dg-do run } */ double d; long double ld; --- libgomp/testsuite/libgomp.c++/atomic-16.C.jj 2021-09-16 20:00:00.633630554 +0200 +++ libgomp/testsuite/libgomp.c++/atomic-16.C 2021-09-16 20:05:16.024318275 +0200 @@ -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); +} --- libgomp/testsuite/libgomp.c++/atomic-17.C.jj 2021-09-16 20:04:22.850045315 +0200 +++ libgomp/testsuite/libgomp.c++/atomic-17.C 2021-09-16 20:08:47.191430123 +0200 @@ -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); +}