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  <ja...@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 <r...@redhat.com>,
                  Diego Novillo <dnovi...@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

Reply via email to