[OPENMP] Additional sema analysis for 'omp atomic[ update]'.
Adds additional semantic analysis + generation of helper expressions for proper codegen.

llvm-svn: 232164
diff --git a/clang/test/OpenMP/atomic_messages.c b/clang/test/OpenMP/atomic_messages.c
index ae490ee..8d4ade6 100644
--- a/clang/test/OpenMP/atomic_messages.c
+++ b/clang/test/OpenMP/atomic_messages.c
@@ -4,14 +4,16 @@
 L1:
   foo();
 #pragma omp atomic
-  // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
   {
     foo();
     goto L1; // expected-error {{use of undeclared label 'L1'}}
   }
   goto L2; // expected-error {{use of undeclared label 'L2'}}
 #pragma omp atomic
-  // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
   {
     foo();
   L2:
@@ -100,3 +102,94 @@
 
   return a.a;
 }
+
+int updateint() {
+  int a = 0, b = 0;
+// Test for atomic update
+#pragma omp atomic update
+  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
+  ;
+#pragma omp atomic
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected built-in binary or unary operator}}
+  foo();
+#pragma omp atomic
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected built-in binary operator}}
+  a = b;
+#pragma omp atomic update
+  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
+  a = b || a;
+#pragma omp atomic update
+  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
+  a = a && b;
+#pragma omp atomic update
+  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected in right hand side of expression}}
+  a = (float)a + b;
+#pragma omp atomic
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected in right hand side of expression}}
+  a = 2 * b;
+#pragma omp atomic
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected in right hand side of expression}}
+  a = b + *&a;
+#pragma omp atomic update
+  *&a = *&a +  2;
+#pragma omp atomic update
+  a++;
+#pragma omp atomic
+  ++a;
+#pragma omp atomic update
+  a--;
+#pragma omp atomic
+  --a;
+#pragma omp atomic update
+  a += b;
+#pragma omp atomic
+  a %= b;
+#pragma omp atomic update
+  a *= b;
+#pragma omp atomic
+  a -= b;
+#pragma omp atomic update
+  a /= b;
+#pragma omp atomic
+  a &= b;
+#pragma omp atomic update
+  a ^= b;
+#pragma omp atomic
+  a |= b;
+#pragma omp atomic update
+  a <<= b;
+#pragma omp atomic
+  a >>= b;
+#pragma omp atomic update
+  a = b + a;
+#pragma omp atomic
+  a = a * b;
+#pragma omp atomic update
+  a = b - a;
+#pragma omp atomic
+  a = a / b;
+#pragma omp atomic update
+  a = b & a;
+#pragma omp atomic
+  a = a ^ b;
+#pragma omp atomic update
+  a = b | a;
+#pragma omp atomic
+  a = a << b;
+#pragma omp atomic
+  a = b >> a;
+  // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}}
+#pragma omp atomic update update
+  a /= b;
+
+  return 0;
+}
+