[OPENMP] Additional processing of 'omp atomic read' directive.
According to OpenMP standard, Section 2.12.6, atomic Construct, '#pragma omp atomic read' is allowed to be used only for expression statements of form 'v = x;', where x and v (as applicable) are both l-value expressions with scalar type. Patch adds checks for it.

llvm-svn: 222231
diff --git a/clang/test/OpenMP/atomic_messages.c b/clang/test/OpenMP/atomic_messages.c
new file mode 100644
index 0000000..d2d3308
--- /dev/null
+++ b/clang/test/OpenMP/atomic_messages.c
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+int foo() {
+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}}
+  {
+    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}}
+  {
+    foo();
+  L2:
+    foo();
+  }
+
+  return 0;
+}
+
+struct S {
+  int a;
+};
+
+int readint() {
+  int a = 0, b = 0;
+// Test for atomic read
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
+  ;
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
+  foo();
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
+  a += b;
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected lvalue expression}}
+  a = 0;
+#pragma omp atomic read
+  a = b;
+  // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
+#pragma omp atomic read read
+  a = b;
+
+  return 0;
+}
+
+int readS() {
+  struct S a, b;
+  // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
+#pragma omp atomic read read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected expression of scalar type}}
+  a = b;
+
+  return a.a;
+}
diff --git a/clang/test/OpenMP/atomic_messages.cpp b/clang/test/OpenMP/atomic_messages.cpp
index b53133f..3965a77 100644
--- a/clang/test/OpenMP/atomic_messages.cpp
+++ b/clang/test/OpenMP/atomic_messages.cpp
@@ -21,31 +21,78 @@
   return 0;
 }
 
+struct S {
+  int a;
+  S &operator=(int v) {
+    a = v;
+    return *this;
+  }
+  S &operator+=(const S &s) {
+    a += s.a;
+    return *this;
+  }
+};
+
 template <class T>
 T read() {
-  T a, b = 0;
+  T a = T(), b = T();
 // Test for atomic read
 #pragma omp atomic read
-  // expected-error@+1 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both l-value expressions with scalar type}}
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
   ;
-// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
+  foo();
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
+  a += b;
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected lvalue expression}}
+  a = 0;
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
+  a = b;
+  // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
 #pragma omp atomic read read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
   a = b;
 
-  return T();
+  return a;
 }
 
 int read() {
-  int a, b = 0;
+  int a = 0, b = 0;
 // Test for atomic read
 #pragma omp atomic read
-  // expected-error@+1 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both l-value expressions with scalar type}}
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
   ;
-// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
+  foo();
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected built-in assignment operator}}
+  a += b;
+#pragma omp atomic read
+  // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
+  // expected-note@+1 {{expected lvalue expression}}
+  a = 0;
+#pragma omp atomic read
+  a = b;
+  // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
 #pragma omp atomic read read
   a = b;
 
-  return read<int>();
+  // expected-note@+1 {{in instantiation of function template specialization 'read<S>' requested here}}
+  return read<int>() + read<S>().a;
 }
 
 template <class T>