aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-09-17 11:28:31 +0200
committerJakub Jelinek <jakub@redhat.com>2021-09-17 11:28:31 +0200
commit3a2bcffac602f5de56537a77db1062984bcefd45 (patch)
treeae688b9db0bfa75b79552f4d331ba4758e7a69cb /gcc/cp/semantics.c
parent48b3caffcacc99adf72ba1be189a7d9ebc4190be (diff)
downloadgcc-3a2bcffac602f5de56537a77db1062984bcefd45.zip
gcc-3a2bcffac602f5de56537a77db1062984bcefd45.tar.gz
gcc-3a2bcffac602f5de56537a77db1062984bcefd45.tar.bz2
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 <jakub@redhat.com> gcc/c-family/ * c-omp.c (c_finish_omp_atomic): Avoid creating TARGET_EXPR if test is true, use create_tmp_var_raw instead of create_tmp_var and add a zero initializer to TARGET_EXPRs that had NULL initializer. When omitting operands after v = x, use type of v rather than type of x. Fix type of vtmp TARGET_EXPR. gcc/c/ * c-parser.c (c_parser_omp_atomic): Reject atomic swap if capture is true. gcc/cp/ * cp-tree.h (finish_omp_atomic): Add r and weak arguments. * parser.c (cp_parser_omp_atomic): Update function comment for OpenMP 5.1 atomics, parse OpenMP 5.1 atomics and fail, compare and weak clauses. * semantics.c (finish_omp_atomic): Add r and weak arguments, handle them, handle COND_EXPRs. * pt.c (tsubst_expr): Adjust for COND_EXPR forms that finish_omp_atomic can now produce. gcc/testsuite/ * c-c++-common/gomp/atomic-18.c: Expect same diagnostics in C++ as in C. * c-c++-common/gomp/atomic-25.c: Drop c effective target. * c-c++-common/gomp/atomic-26.c: Likewise. * c-c++-common/gomp/atomic-27.c: Likewise. * c-c++-common/gomp/atomic-28.c: Likewise. * c-c++-common/gomp/atomic-29.c: Likewise. * c-c++-common/gomp/atomic-30.c: Likewise. Adjust expected diagnostics for C++ when it differs from C. (foo): Change return type from double to void. * g++.dg/gomp/atomic-5.C: Adjust expected diagnostics wording. * g++.dg/gomp/atomic-20.C: New test. libgomp/ * testsuite/libgomp.c-c++-common/atomic-19.c: Drop c effective target. Use /* */ comments instead of //. * testsuite/libgomp.c-c++-common/atomic-20.c: Likewise. * testsuite/libgomp.c-c++-common/atomic-21.c: Likewise. * testsuite/libgomp.c++/atomic-16.C: New test. * testsuite/libgomp.c++/atomic-17.C: New test.
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 94e6b18..35a7b9f 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);
}