* [gomp3.1] #pragma omp atomic updates and fixes
@ 2011-07-30 20:32 Jakub Jelinek
0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2011-07-30 20:32 UTC (permalink / raw)
To: gcc-patches
Hi!
This patch implements the remaining changes from in between 3.1 draft and
3.1 final, in the light of the
http://www.openmp.org/forum/viewtopic.php?f=10&t=1199
clarification.
#pragma omp atomic
x = x + 6 + 2;
is now allowed, as well as
#pragma omp atomic capture
{ x = x | 7 + 1; v = x; }
etc. In the C FE I had to change c_parser_binary_expression slightly, like
I've changed cp_parser_binary_expression already a few years ago for OpenMP
3.0, because we don't want to parse
#pragma omp atomic
x = x * 6 + 2;
as if it was x = x * (6 + 2);. Regtested on x86_64-linux, committed to
gomp-3_1-branch.
2011-07-30 Jakub Jelinek <jakub@redhat.com>
* c-common.h (c_finish_omp_atomic): Add rhs1 argument.
* c-omp.c (c_finish_omp_atomic): Add rhs1 argument. If it
has side-effects, evaluate those too in the right spot,
if it is a decl and lhs is also a decl, error out if they
aren't the same. Fix order of omit_two_operands_loc arguments.
* c-parser.c (enum c_parser_prec): New enum, moved from within
c_parser_binary_expression.
(c_parser_binary_expression): Add PREC argument. Stop parsing
if operator has lower or equal precedence than PREC.
(c_parser_conditional_expression, c_parser_omp_for_loop): Adjust
callers.
(c_parser_omp_atomic): Parse x = x binop expr; stmts in
#pragma omp atomic update and in #pragma omp atomic capture
structured block forms. Adjust c_finish_omp_atomic caller.
Fix up error handling in capture structured blocks.
* cp-tree.h (finish_omp_atomic): Add rhs1 argument.
* parser.c (cp_parser_omp_atomic): Parse x = x binop expr; stmts in
#pragma omp atomic update and in #pragma omp atomic capture
structured block forms. Adjust finish_omp_atomic caller.
Fix up error handling in capture structured blocks.
* pt.c (tsubst_expr) <case OMP_ATOMIC>: Find saved rhs1 value if any
and pass it to finish_omp_atomic.
* semantics.c (finish_omp_atomic): Add rhs1 argument. Adjust
c_finish_omp_atomic caller and store rhs1 inside of OMP_ATOMIC
arguments.
* gcc.dg/gomp/atomic-5.c: Adjust expected diagnostics.
* gcc.dg/gomp/atomic-15.c: New test.
* g++.dg/gomp/atomic-5.C: Adjust expected diagnostics.
* g++.dg/gomp/atomic-15.C: New test.
* testsuite/libgomp.c/atomic-14.c: New test.
* testsuite/libgomp.c++/atomic-8.C: New test.
* testsuite/libgomp.c++/atomic-9.C: New test.
--- gcc/c-family/c-common.h.jj 2011-07-11 17:33:51.000000000 +0200
+++ gcc/c-family/c-common.h 2011-07-30 15:00:38.000000000 +0200
@@ -1005,7 +1005,7 @@ extern tree c_finish_omp_critical (locat
extern tree c_finish_omp_ordered (location_t, tree);
extern void c_finish_omp_barrier (location_t);
extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
- tree, tree, tree, tree);
+ tree, tree, tree, tree, tree);
extern void c_finish_omp_flush (location_t);
extern void c_finish_omp_taskwait (location_t);
extern void c_finish_omp_taskyield (location_t);
--- gcc/c-family/c-omp.c.jj 2011-07-11 19:57:49.000000000 +0200
+++ gcc/c-family/c-omp.c 2011-07-30 14:59:03.000000000 +0200
@@ -1,7 +1,8 @@
/* This file contains routines to construct GNU OpenMP constructs,
called from parsing in the C and C++ front ends.
- Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>,
Diego Novillo <dnovillo@redhat.com>.
@@ -122,12 +123,13 @@ c_finish_omp_taskyield (location_t loc)
tree
c_finish_omp_atomic (location_t loc, enum tree_code code,
enum tree_code opcode, tree lhs, tree rhs,
- tree v, tree lhs1)
+ tree v, tree lhs1, tree rhs1)
{
tree x, type, addr;
if (lhs == error_mark_node || rhs == error_mark_node
- || v == error_mark_node || lhs1 == error_mark_node)
+ || v == error_mark_node || lhs1 == error_mark_node
+ || rhs1 == error_mark_node)
return error_mark_node;
/* ??? According to one reading of the OpenMP spec, complex type are
@@ -188,6 +190,20 @@ c_finish_omp_atomic (location_t loc, enu
x = build2 (code, type, addr, rhs);
SET_EXPR_LOCATION (x, loc);
+ /* Generally it is hard to prove lhs1 and lhs are the same memory
+ location, just diagnose different variables. */
+ if (rhs1
+ && TREE_CODE (rhs1) == VAR_DECL
+ && TREE_CODE (lhs) == VAR_DECL
+ && rhs1 != lhs)
+ {
+ if (code == OMP_ATOMIC)
+ error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory");
+ else
+ error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
+ return error_mark_node;
+ }
+
if (code != OMP_ATOMIC)
{
/* Generally it is hard to prove lhs1 and lhs are the same memory
@@ -202,6 +218,13 @@ c_finish_omp_atomic (location_t loc, enu
}
x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
loc, x, NULL_TREE);
+ if (rhs1 && rhs1 != lhs)
+ {
+ tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
+ if (rhs1addr == error_mark_node)
+ return error_mark_node;
+ x = omit_one_operand_loc (loc, type, x, rhs1addr);
+ }
if (lhs1 && lhs1 != lhs)
{
tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, 0);
@@ -212,10 +235,17 @@ c_finish_omp_atomic (location_t loc, enu
else
{
x = save_expr (x);
- x = omit_two_operands_loc (loc, type, x, lhs1addr, x);
+ x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
}
}
}
+ else if (rhs1 && rhs1 != lhs)
+ {
+ tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
+ if (rhs1addr == error_mark_node)
+ return error_mark_node;
+ x = omit_one_operand_loc (loc, type, x, rhs1addr);
+ }
return x;
}
--- gcc/c-parser.c.jj 2011-07-12 13:10:57.000000000 +0200
+++ gcc/c-parser.c 2011-07-30 17:56:18.000000000 +0200
@@ -1090,6 +1090,23 @@ typedef enum c_dtr_syn {
C_DTR_PARM
} c_dtr_syn;
+/* The binary operation precedence levels, where 0 is a dummy lowest level
+ used for the bottom of the stack. */
+enum c_parser_prec {
+ PREC_NONE,
+ PREC_LOGOR,
+ PREC_LOGAND,
+ PREC_BITOR,
+ PREC_BITXOR,
+ PREC_BITAND,
+ PREC_EQ,
+ PREC_REL,
+ PREC_SHIFT,
+ PREC_ADD,
+ PREC_MULT,
+ NUM_PRECS
+};
+
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
@@ -1138,7 +1155,8 @@ static tree c_parser_asm_clobbers (c_par
static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
static struct c_expr c_parser_conditional_expression (c_parser *,
struct c_expr *);
-static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *);
+static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
+ enum c_parser_prec);
static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
static struct c_expr c_parser_unary_expression (c_parser *);
static struct c_expr c_parser_sizeof_expression (c_parser *);
@@ -5309,7 +5327,7 @@ c_parser_conditional_expression (c_parse
gcc_assert (!after || c_dialect_objc ());
- cond = c_parser_binary_expression (parser, after);
+ cond = c_parser_binary_expression (parser, after, PREC_NONE);
if (c_parser_next_token_is_not (parser, CPP_QUERY))
return cond;
@@ -5394,7 +5412,8 @@ c_parser_conditional_expression (c_parse
/* Parse a binary expression; that is, a logical-OR-expression (C90
6.3.5-6.3.14, C99 6.5.5-6.5.14). If AFTER is not NULL then it is
an Objective-C message expression which is the primary-expression
- starting the expression as an initializer.
+ starting the expression as an initializer. PREC is the starting
+ precedence, usually PREC_NONE.
multiplicative-expression:
cast-expression
@@ -5446,7 +5465,8 @@ c_parser_conditional_expression (c_parse
*/
static struct c_expr
-c_parser_binary_expression (c_parser *parser, struct c_expr *after)
+c_parser_binary_expression (c_parser *parser, struct c_expr *after,
+ enum c_parser_prec prec)
{
/* A binary expression is parsed using operator-precedence parsing,
with the operands being cast expressions. All the binary
@@ -5469,28 +5489,12 @@ c_parser_binary_expression (c_parser *pa
expressions, we also need to adjust c_inhibit_evaluation_warnings
as appropriate when the operators are pushed and popped. */
- /* The precedence levels, where 0 is a dummy lowest level used for
- the bottom of the stack. */
- enum prec {
- PREC_NONE,
- PREC_LOGOR,
- PREC_LOGAND,
- PREC_BITOR,
- PREC_BITXOR,
- PREC_BITAND,
- PREC_EQ,
- PREC_REL,
- PREC_SHIFT,
- PREC_ADD,
- PREC_MULT,
- NUM_PRECS
- };
struct {
/* The expression at this stack level. */
struct c_expr expr;
/* The precedence of the operator on its left, PREC_NONE at the
bottom of the stack. */
- enum prec prec;
+ enum c_parser_prec prec;
/* The operation on its left. */
enum tree_code op;
/* The source location of this operation. */
@@ -5529,11 +5533,11 @@ c_parser_binary_expression (c_parser *pa
gcc_assert (!after || c_dialect_objc ());
stack[0].loc = c_parser_peek_token (parser)->location;
stack[0].expr = c_parser_cast_expression (parser, after);
- stack[0].prec = PREC_NONE;
+ stack[0].prec = prec;
sp = 0;
while (true)
{
- enum prec oprec;
+ enum c_parser_prec oprec;
enum tree_code ocode;
if (parser->error)
goto out;
@@ -5617,9 +5621,13 @@ c_parser_binary_expression (c_parser *pa
goto out;
}
binary_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
while (oprec <= stack[sp].prec)
- POP;
+ {
+ if (sp == 0)
+ goto out;
+ POP;
+ }
+ c_parser_consume_token (parser);
switch (ocode)
{
case TRUTH_ANDIF_EXPR:
@@ -9135,6 +9143,9 @@ c_parser_omp_structured_block (c_parser
where x is an lvalue expression with scalar type.
OpenMP 3.1:
+ # pragma omp atomic new-line
+ update-stmt
+
# pragma omp atomic read new-line
read-stmt
@@ -9142,7 +9153,7 @@ c_parser_omp_structured_block (c_parser
write-stmt
# pragma omp atomic update new-line
- expression-stmt
+ update-stmt
# pragma omp atomic capture new-line
capture-stmt
@@ -9154,10 +9165,12 @@ c_parser_omp_structured_block (c_parser
v = x
write-stmt:
x = expr
+ update-stmt:
+ expression-stmt | x = x binop expr
capture-stmt:
v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
capture-block:
- { v = x; expression-stmt; } | { expression-stmt; v = x; }
+ { v = x; update-stmt; } | { update-stmt; v = x; }
where x and v are lvalue expressions with scalar type.
@@ -9166,7 +9179,8 @@ c_parser_omp_structured_block (c_parser
static void
c_parser_omp_atomic (location_t loc, c_parser *parser)
{
- tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
+ tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
+ tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
tree stmt, orig_lhs;
enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
struct c_expr rhs_expr;
@@ -9250,6 +9264,17 @@ restart:
case ERROR_MARK:
saw_error:
c_parser_skip_to_end_of_block_or_statement (parser);
+ if (structured_block)
+ {
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ c_parser_consume_token (parser);
+ else if (code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ c_parser_consume_token (parser);
+ }
+ }
return;
case POSTINCREMENT_EXPR:
@@ -9347,19 +9372,85 @@ restart:
opcode = BIT_XOR_EXPR;
break;
case CPP_EQ:
- if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ if (structured_block || code == OMP_ATOMIC)
{
- code = OMP_ATOMIC_CAPTURE_OLD;
- v = lhs;
- lhs = NULL_TREE;
+ location_t aloc = c_parser_peek_token (parser)->location;
+ location_t rhs_loc;
+ enum c_parser_prec oprec = PREC_NONE;
+
c_parser_consume_token (parser);
- lhs1 = c_parser_unary_expression (parser).value;
- lhs1 = c_fully_fold (lhs1, false, NULL);
- if (lhs1 == error_mark_node)
- goto saw_error;
- if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ rhs1 = c_parser_unary_expression (parser).value;
+ rhs1 = c_fully_fold (rhs1, false, NULL);
+ if (rhs1 == error_mark_node)
goto saw_error;
- goto restart;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_SEMICOLON:
+ if (code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ v = lhs;
+ lhs = NULL_TREE;
+ lhs1 = rhs1;
+ rhs1 = NULL_TREE;
+ c_parser_consume_token (parser);
+ goto restart;
+ }
+ c_parser_error (parser,
+ "invalid form of %<#pragma omp atomic%>");
+ goto saw_error;
+ case CPP_MULT:
+ opcode = MULT_EXPR;
+ oprec = PREC_MULT;
+ break;
+ case CPP_DIV:
+ opcode = TRUNC_DIV_EXPR;
+ oprec = PREC_MULT;
+ break;
+ case CPP_PLUS:
+ opcode = PLUS_EXPR;
+ oprec = PREC_ADD;
+ break;
+ case CPP_MINUS:
+ opcode = MINUS_EXPR;
+ oprec = PREC_ADD;
+ break;
+ case CPP_LSHIFT:
+ opcode = LSHIFT_EXPR;
+ oprec = PREC_SHIFT;
+ break;
+ case CPP_RSHIFT:
+ opcode = RSHIFT_EXPR;
+ oprec = PREC_SHIFT;
+ break;
+ case CPP_AND:
+ opcode = BIT_AND_EXPR;
+ oprec = PREC_BITAND;
+ break;
+ case CPP_OR:
+ opcode = BIT_IOR_EXPR;
+ oprec = PREC_BITOR;
+ break;
+ case CPP_XOR:
+ opcode = BIT_XOR_EXPR;
+ oprec = PREC_BITXOR;
+ break;
+ default:
+ c_parser_error (parser,
+ "invalid operator for %<#pragma omp atomic%>");
+ goto saw_error;
+ }
+ loc = aloc;
+ c_parser_consume_token (parser);
+ rhs_loc = c_parser_peek_token (parser)->location;
+ if (commutative_tree_code (opcode))
+ oprec = (enum c_parser_prec) (oprec - 1);
+ rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
+ rhs_expr = default_function_array_read_conversion (rhs_loc,
+ rhs_expr);
+ rhs = rhs_expr.value;
+ rhs = c_fully_fold (rhs, false, NULL);
+ goto stmt_done;
}
/* FALLTHROUGH */
default:
@@ -9381,6 +9472,7 @@ restart:
rhs = c_fully_fold (rhs, false, NULL);
break;
}
+stmt_done:
if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
{
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
@@ -9402,7 +9494,7 @@ restart:
c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
}
done:
- stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1);
+ stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
if (stmt != error_mark_node)
add_stmt (stmt);
@@ -9570,7 +9662,8 @@ c_parser_omp_for_loop (location_t loc,
if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
{
location_t cond_loc = c_parser_peek_token (parser)->location;
- struct c_expr cond_expr = c_parser_binary_expression (parser, NULL);
+ struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
+ PREC_NONE);
cond = cond_expr.value;
cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
--- gcc/cp/cp-tree.h.jj 2011-07-29 18:34:03.000000000 +0200
+++ gcc/cp/cp-tree.h 2011-07-30 14:24:00.000000000 +0200
@@ -5449,7 +5449,7 @@ extern tree finish_omp_task (tree, tre
extern tree finish_omp_for (location_t, tree, tree,
tree, tree, tree, tree, tree);
extern void finish_omp_atomic (enum tree_code, enum tree_code,
- tree, tree, tree, tree);
+ tree, tree, tree, tree, tree);
extern void finish_omp_barrier (void);
extern void finish_omp_flush (void);
extern void finish_omp_taskwait (void);
--- gcc/cp/parser.c.jj 2011-07-12 13:48:18.000000000 +0200
+++ gcc/cp/parser.c 2011-07-30 17:32:34.000000000 +0200
@@ -24197,6 +24197,9 @@ cp_parser_omp_structured_block (cp_parse
where x is an lvalue expression with scalar type.
OpenMP 3.1:
+ # pragma omp atomic new-line
+ update-stmt
+
# pragma omp atomic read new-line
read-stmt
@@ -24204,7 +24207,7 @@ cp_parser_omp_structured_block (cp_parse
write-stmt
# pragma omp atomic update new-line
- expression-stmt
+ update-stmt
# pragma omp atomic capture new-line
capture-stmt
@@ -24216,10 +24219,12 @@ cp_parser_omp_structured_block (cp_parse
v = x
write-stmt:
x = expr
+ update-stmt:
+ expression-stmt | x = x binop expr
capture-stmt:
v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
capture-block:
- { v = x; expression-stmt; } | { expression-stmt; v = x; }
+ { v = x; update-stmt; } | { update-stmt; v = x; }
where x and v are lvalue expressions with scalar type. */
@@ -24227,7 +24232,7 @@ static void
cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
{
tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
- tree orig_lhs;
+ tree rhs1 = NULL_TREE, orig_lhs;
enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
bool structured_block = false;
@@ -24387,19 +24392,74 @@ restart:
opcode = BIT_XOR_EXPR;
break;
case CPP_EQ:
- if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ if (structured_block || code == OMP_ATOMIC)
{
- code = OMP_ATOMIC_CAPTURE_OLD;
- v = lhs;
- lhs = NULL_TREE;
+ enum cp_parser_prec oprec;
+ cp_token *token;
cp_lexer_consume_token (parser->lexer);
- lhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
+ rhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
/*cast_p=*/false, NULL);
- if (lhs1 == error_mark_node)
+ if (rhs1 == error_mark_node)
goto saw_error;
- if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ token = cp_lexer_peek_token (parser->lexer);
+ switch (token->type)
+ {
+ case CPP_SEMICOLON:
+ if (code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ v = lhs;
+ lhs = NULL_TREE;
+ lhs1 = rhs1;
+ rhs1 = NULL_TREE;
+ cp_lexer_consume_token (parser->lexer);
+ goto restart;
+ }
+ cp_parser_error (parser,
+ "invalid form of %<#pragma omp atomic%>");
+ goto saw_error;
+ case CPP_MULT:
+ opcode = MULT_EXPR;
+ break;
+ case CPP_DIV:
+ opcode = TRUNC_DIV_EXPR;
+ break;
+ case CPP_PLUS:
+ opcode = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ opcode = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT:
+ opcode = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT:
+ opcode = RSHIFT_EXPR;
+ break;
+ case CPP_AND:
+ opcode = BIT_AND_EXPR;
+ break;
+ case CPP_OR:
+ opcode = BIT_IOR_EXPR;
+ break;
+ case CPP_XOR:
+ opcode = BIT_XOR_EXPR;
+ break;
+ default:
+ cp_parser_error (parser,
+ "invalid operator for %<#pragma omp atomic%>");
+ goto saw_error;
+ }
+ oprec = TOKEN_PRECEDENCE (token);
+ gcc_assert (oprec != PREC_NOT_OPERATOR);
+ if (commutative_tree_code (opcode))
+ oprec = (enum cp_parser_prec) (oprec - 1);
+ cp_lexer_consume_token (parser->lexer);
+ rhs = cp_parser_binary_expression (parser, false, false,
+ oprec, NULL);
+ if (rhs == error_mark_node)
goto saw_error;
- goto restart;
+ goto stmt_done;
}
/* FALLTHROUGH */
default:
@@ -24414,6 +24474,7 @@ restart:
goto saw_error;
break;
}
+stmt_done:
if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
{
if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
@@ -24435,13 +24496,24 @@ restart:
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
}
done:
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1);
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
if (!structured_block)
cp_parser_consume_semicolon_at_end_of_statement (parser);
return;
saw_error:
cp_parser_skip_to_end_of_block_or_statement (parser);
+ if (structured_block)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ cp_lexer_consume_token (parser->lexer);
+ else if (code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
}
--- gcc/cp/pt.c.jj 2011-07-11 17:43:38.000000000 +0200
+++ gcc/cp/pt.c 2011-07-30 15:17:47.000000000 +0200
@@ -12525,15 +12525,23 @@ tsubst_expr (tree t, tree args, tsubst_f
if (TREE_CODE (TREE_OPERAND (t, 1)) != MODIFY_EXPR)
{
tree op1 = TREE_OPERAND (t, 1);
- tree lhs = RECUR (TREE_OPERAND (op1, 0));
- tree rhs = RECUR (TREE_OPERAND (op1, 1));
+ tree rhs1 = 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));
finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
- NULL_TREE, NULL_TREE);
+ NULL_TREE, NULL_TREE, rhs1);
}
else
{
tree op1 = TREE_OPERAND (t, 1);
tree v = NULL_TREE, lhs, rhs = NULL_TREE, lhs1 = NULL_TREE;
+ tree rhs1 = NULL_TREE;
enum tree_code code = TREE_CODE (TREE_OPERAND (op1, 1));
enum tree_code opcode = NOP_EXPR;
if (code == OMP_ATOMIC_READ)
@@ -12547,6 +12555,11 @@ tsubst_expr (tree t, tree args, tsubst_f
tree op11 = TREE_OPERAND (TREE_OPERAND (op1, 1), 1);
v = RECUR (TREE_OPERAND (op1, 0));
lhs1 = RECUR (TREE_OPERAND (TREE_OPERAND (op1, 1), 0));
+ if (TREE_CODE (op11) == COMPOUND_EXPR)
+ {
+ rhs1 = RECUR (TREE_OPERAND (op11, 0));
+ op11 = TREE_OPERAND (op11, 1);
+ }
lhs = RECUR (TREE_OPERAND (op11, 0));
rhs = RECUR (TREE_OPERAND (op11, 1));
opcode = TREE_CODE (op11);
@@ -12557,7 +12570,7 @@ tsubst_expr (tree t, tree args, tsubst_f
lhs = RECUR (TREE_OPERAND (op1, 0));
rhs = RECUR (TREE_OPERAND (op1, 1));
}
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1);
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
}
break;
--- gcc/cp/semantics.c.jj 2011-07-29 18:34:34.000000000 +0200
+++ gcc/cp/semantics.c 2011-07-30 15:05:41.000000000 +0200
@@ -4713,12 +4713,13 @@ finish_omp_for (location_t locus, tree d
void
finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
- tree rhs, tree v, tree lhs1)
+ tree rhs, tree v, tree lhs1, tree rhs1)
{
tree orig_lhs;
tree orig_rhs;
tree orig_v;
tree orig_lhs1;
+ tree orig_rhs1;
bool dependent_p;
tree stmt;
@@ -4726,6 +4727,7 @@ finish_omp_atomic (enum tree_code code,
orig_rhs = rhs;
orig_v = v;
orig_lhs1 = lhs1;
+ orig_rhs1 = rhs1;
dependent_p = false;
stmt = NULL_TREE;
@@ -4736,7 +4738,8 @@ finish_omp_atomic (enum tree_code code,
dependent_p = (type_dependent_expression_p (lhs)
|| (rhs && type_dependent_expression_p (rhs))
|| (v && type_dependent_expression_p (v))
- || (lhs1 && type_dependent_expression_p (lhs1)));
+ || (lhs1 && type_dependent_expression_p (lhs1))
+ || (rhs1 && type_dependent_expression_p (rhs1)));
if (!dependent_p)
{
lhs = build_non_dependent_expr (lhs);
@@ -4746,12 +4749,14 @@ finish_omp_atomic (enum tree_code code,
v = build_non_dependent_expr (v);
if (lhs1)
lhs1 = build_non_dependent_expr (lhs1);
+ if (rhs1)
+ rhs1 = build_non_dependent_expr (rhs1);
}
}
if (!dependent_p)
{
stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
- v, lhs1);
+ v, lhs1, rhs1);
if (stmt == error_mark_node)
return;
}
@@ -4768,6 +4773,8 @@ finish_omp_atomic (enum tree_code code,
stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
else
stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
+ if (orig_rhs1)
+ stmt = build_min_nt (COMPOUND_EXPR, orig_rhs1, stmt);
if (code != OMP_ATOMIC)
{
stmt = build_min_nt (code, orig_lhs1, stmt);
--- gcc/testsuite/gcc.dg/gomp/atomic-15.c.jj 2011-07-30 17:46:15.000000000 +0200
+++ gcc/testsuite/gcc.dg/gomp/atomic-15.c 2011-07-30 17:45:20.000000000 +0200
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+int x = 6;
+
+int
+main ()
+{
+ int v;
+ #pragma omp atomic
+ x = x * 7 + 6; /* { dg-error "expected" } */
+ #pragma omp atomic
+ x = x * 7 ^ 6; /* { dg-error "expected" } */
+ #pragma omp atomic update
+ x = x - 8 + 6; /* { dg-error "expected" } */
+ #pragma omp atomic
+ x = x ^ 7 | 2; /* { dg-error "expected" } */
+ #pragma omp atomic
+ x = x / 7 * 2; /* { dg-error "expected" } */
+ #pragma omp atomic
+ x = x / 7 / 2; /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ v = x = x | 6; /* { dg-error "invalid operator" } */
+ #pragma omp atomic capture
+ { v = x; x = x * 7 + 6; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { v = x; x = x * 7 ^ 6; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { v = x; x = x - 8 + 6; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { v = x; x = x ^ 7 | 2; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { v = x; x = x / 7 * 2; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { v = x; x = x / 7 / 2; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { x = x * 7 + 6; v = x; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { x = x * 7 ^ 6; v = x; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { x = x - 8 + 6; v = x; } /* { dg-error "expected" } */
+ #pragma omp atomic capture
+ { x = x ^ 7 | 2; v = x; } /* { dg-error "expected" } */
+ (void) v;
+ return 0;
+}
--- gcc/testsuite/gcc.dg/gomp/atomic-5.c.jj 2011-02-24 14:13:38.000000000 +0100
+++ gcc/testsuite/gcc.dg/gomp/atomic-5.c 2011-07-30 17:42:04.000000000 +0200
@@ -11,9 +11,9 @@ void f1(void)
#pragma omp atomic
x %= 2; /* { dg-error "invalid operator" } */
#pragma omp atomic
- x = x + 1; /* { dg-error "invalid operator" } */
+ x = x + 1;
#pragma omp atomic
- x = 1; /* { dg-error "invalid operator" } */
+ x = 1; /* { dg-error "invalid form" } */
#pragma omp atomic
++y; /* { dg-error "read-only variable" } */
#pragma omp atomic
--- gcc/testsuite/g++.dg/gomp/atomic-15.C.jj 2011-07-30 17:34:51.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/atomic-15.C 2011-07-30 17:33:18.000000000 +0200
@@ -0,0 +1,46 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+int x = 6;
+
+int
+main ()
+{
+ int v;
+ #pragma omp atomic
+ x = x * 7 + 6; // { dg-error "expected" }
+ #pragma omp atomic
+ x = x * 7 ^ 6; // { dg-error "expected" }
+ #pragma omp atomic update
+ x = x - 8 + 6; // { dg-error "expected" }
+ #pragma omp atomic
+ x = x ^ 7 | 2; // { dg-error "expected" }
+ #pragma omp atomic
+ x = x / 7 * 2; // { dg-error "expected" }
+ #pragma omp atomic
+ x = x / 7 / 2; // { dg-error "expected" }
+ #pragma omp atomic capture
+ v = x = x | 6; // { dg-error "invalid operator" }
+ #pragma omp atomic capture
+ { v = x; x = x * 7 + 6; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { v = x; x = x * 7 ^ 6; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { v = x; x = x - 8 + 6; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { v = x; x = x ^ 7 | 2; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { v = x; x = x / 7 * 2; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { v = x; x = x / 7 / 2; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { x = x * 7 + 6; v = x; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { x = x * 7 ^ 6; v = x; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { x = x - 8 + 6; v = x; } // { dg-error "expected" }
+ #pragma omp atomic capture
+ { x = x ^ 7 | 2; v = x; } // { dg-error "expected" }
+ (void) v;
+ return 0;
+}
--- gcc/testsuite/g++.dg/gomp/atomic-5.C.jj 2011-02-24 14:16:31.000000000 +0100
+++ gcc/testsuite/g++.dg/gomp/atomic-5.C 2011-07-30 17:41:15.000000000 +0200
@@ -9,9 +9,9 @@ void f1(void)
#pragma omp atomic
x %= 2; /* { dg-error "invalid operator" } */
#pragma omp atomic
- x = x + 1; /* { dg-error "invalid operator" } */
+ x = x + 1;
#pragma omp atomic
- x = 1; /* { dg-error "invalid operator" } */
+ x = 1; /* { dg-error "invalid form" } */
#pragma omp atomic
++y; /* { dg-error "read-only variable" } */
#pragma omp atomic
--- libgomp/testsuite/libgomp.c/atomic-14.c.jj 2011-07-30 17:45:48.000000000 +0200
+++ libgomp/testsuite/libgomp.c/atomic-14.c 2011-07-30 17:44:08.000000000 +0200
@@ -0,0 +1,137 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int x = 6, cnt;
+
+int
+foo (void)
+{
+ return cnt++;
+}
+
+int
+main ()
+{
+ int v, *p;
+ #pragma omp atomic update
+ x = x + 7;
+ #pragma omp atomic
+ x = x + 7 + 6;
+ #pragma omp atomic update
+ x = x + 2 * 3;
+ #pragma omp atomic
+ x = x * (2 - 1);
+ #pragma omp atomic read
+ v = x;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic write
+ x = 0;
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 1 ^ 2;
+ }
+ if (v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 4 | 2;
+ }
+ if (v != 3)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 7)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x = x ^ 6 & 2;
+ v = x;
+ }
+ if (v != 5)
+ abort ();
+ #pragma omp atomic capture
+ { x = x - (6 + 4); v = x; }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = x - (1 | 2); }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic
+ x = x * -4 / 2;
+ #pragma omp atomic read
+ v = x;
+ if (v != 16)
+ abort ();
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = p[foo (), 0] - 16;
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] += 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 4 || v != 6)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] += 6;
+ }
+ if (cnt != 6 || v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 9 || v != 18)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] = p[foo (), 0] + 6;
+ }
+ if (cnt != 12 || v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 24)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]++; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; ++p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]++; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { ++p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 20 || v != 28)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]--; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; --p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]--; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { --p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 28 || v != 24)
+ abort ();
+ return 0;
+}
--- libgomp/testsuite/libgomp.c++/atomic-8.C.jj 2011-07-30 17:22:09.000000000 +0200
+++ libgomp/testsuite/libgomp.c++/atomic-8.C 2011-07-30 17:37:05.000000000 +0200
@@ -0,0 +1,137 @@
+// { dg-do run }
+
+extern "C" void abort ();
+int x = 6, cnt;
+
+int
+foo ()
+{
+ return cnt++;
+}
+
+int
+main ()
+{
+ int v, *p;
+ #pragma omp atomic update
+ x = x + 7;
+ #pragma omp atomic
+ x = x + 7 + 6;
+ #pragma omp atomic update
+ x = x + 2 * 3;
+ #pragma omp atomic
+ x = x * (2 - 1);
+ #pragma omp atomic read
+ v = x;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic write
+ x = 0;
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 1 ^ 2;
+ }
+ if (v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 4 | 2;
+ }
+ if (v != 3)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 7)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x = x ^ 6 & 2;
+ v = x;
+ }
+ if (v != 5)
+ abort ();
+ #pragma omp atomic capture
+ { x = x - (6 + 4); v = x; }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = x - (1 | 2); }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic
+ x = x * -4 / 2;
+ #pragma omp atomic read
+ v = x;
+ if (v != 16)
+ abort ();
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = p[foo (), 0] - 16;
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] += 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 4 || v != 6)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] += 6;
+ }
+ if (cnt != 6 || v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 9 || v != 18)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] = p[foo (), 0] + 6;
+ }
+ if (cnt != 12 || v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 24)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]++; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; ++p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]++; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { ++p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 20 || v != 28)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]--; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; --p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]--; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { --p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 28 || v != 24)
+ abort ();
+ return 0;
+}
--- libgomp/testsuite/libgomp.c++/atomic-9.C.jj 2011-07-30 17:35:13.000000000 +0200
+++ libgomp/testsuite/libgomp.c++/atomic-9.C 2011-07-30 17:37:47.000000000 +0200
@@ -0,0 +1,148 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+int cnt;
+
+int
+foo ()
+{
+ return cnt++;
+}
+
+template <typename T>
+void
+bar ()
+{
+ extern T x;
+ T v, *p;
+ #pragma omp atomic update
+ x = x + 7;
+ #pragma omp atomic
+ x = x + 7 + 6;
+ #pragma omp atomic update
+ x = x + 2 * 3;
+ #pragma omp atomic
+ x = x * (2 - 1);
+ #pragma omp atomic read
+ v = x;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic write
+ x = 0;
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 1 ^ 2;
+ }
+ if (v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 4 | 2;
+ }
+ if (v != 3)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 7)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x = x ^ 6 & 2;
+ v = x;
+ }
+ if (v != 5)
+ abort ();
+ #pragma omp atomic capture
+ { x = x - (6 + 4); v = x; }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = x - (1 | 2); }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic
+ x = x * -4 / 2;
+ #pragma omp atomic read
+ v = x;
+ if (v != 16)
+ abort ();
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = p[foo (), 0] - 16;
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] += 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 4 || v != 6)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] += 6;
+ }
+ if (cnt != 6 || v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 9 || v != 18)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] = p[foo (), 0] + 6;
+ }
+ if (cnt != 12 || v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 24)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]++; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; ++p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]++; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { ++p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 20 || v != 28)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]--; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; --p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]--; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { --p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 28 || v != 24)
+ abort ();
+}
+
+int x = 6;
+
+int
+main ()
+{
+ bar <int> ();
+ return 0;
+}
Jakub
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-07-30 16:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-30 20:32 [gomp3.1] #pragma omp atomic updates and fixes Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).