r222913 - [OPENMP] Additional processing of 'omp atomic write' directive.

Alexey Bataev a.bataev at hotmail.com
Thu Nov 27 23:21:40 PST 2014


Author: abataev
Date: Fri Nov 28 01:21:40 2014
New Revision: 222913

URL: http://llvm.org/viewvc/llvm-project?rev=222913&view=rev
Log:
[OPENMP] Additional processing of 'omp atomic write' directive.
According to OpenMP standard, Section 2.12.6, atomic Construct, '#pragma omp atomic write' is allowed to be used only for expression statements of form 'x = expr;', where x is a lvalue expression and expr is an expression with scalar type. Patch adds checks for it.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/atomic_messages.c
    cfe/trunk/test/OpenMP/atomic_messages.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Nov 28 01:21:40 2014
@@ -7357,11 +7357,11 @@ def err_omp_parallel_reduction_in_task_f
 def err_omp_atomic_read_not_expression_statement : Error<
   "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">;
-def note_omp_atomic_read: Note<
+def note_omp_atomic_read_write: Note<
   "%select{expected an expression statement|expected built-in assignment operator|expected expression of scalar type|expected lvalue expression}0">;
 def err_omp_atomic_write_not_expression_statement : Error<
   "the statement for 'atomic write' must be an expression statement of form 'x = expr;',"
-  " where x is an l-value expression with scalar type">;
+  " where x is a lvalue expression with scalar type">;
 def err_omp_atomic_update_not_expression_statement : Error<
   "the statement for 'atomic%select{| update}0' 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">;

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Nov 28 01:21:40 2014
@@ -3222,14 +3222,14 @@ StmtResult Sema::ActOnOpenMPAtomicDirect
   // expr or subexpressions of expr.
   // * For forms that allow multiple occurrences of x, the number of times
   // that x is evaluated is unspecified.
+  enum {
+    NotAnExpression,
+    NotAnAssignmentOp,
+    NotAScalarType,
+    NotAnLValue,
+    NoError
+  } ErrorFound = NoError;
   if (AtomicKind == OMPC_read) {
-    enum {
-      NotAnExpression,
-      NotAnAssignmentOp,
-      NotAScalarType,
-      NotAnLValue,
-      NoError
-    } ErrorFound = NoError;
     SourceLocation ErrorLoc, NoteLoc;
     SourceRange ErrorRange, NoteRange;
     // If clause is read:
@@ -3279,16 +3279,65 @@ StmtResult Sema::ActOnOpenMPAtomicDirect
     if (ErrorFound != NoError) {
       Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
           << ErrorRange;
-      Diag(NoteLoc, diag::note_omp_atomic_read) << ErrorFound << NoteRange;
+      Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
+                                                      << NoteRange;
       return StmtError();
     } else if (CurContext->isDependentContext())
       V = X = nullptr;
   } else if (AtomicKind == OMPC_write) {
-    if (!isa<Expr>(Body)) {
-      Diag(Body->getLocStart(),
-           diag::err_omp_atomic_write_not_expression_statement);
-      return StmtError();
+    SourceLocation ErrorLoc, NoteLoc;
+    SourceRange ErrorRange, NoteRange;
+    // If clause is write:
+    //  x = expr;
+    if (auto AtomicBody = dyn_cast<Expr>(Body)) {
+      auto AtomicBinOp =
+          dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
+      if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
+        X = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
+        E = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
+        if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
+            (E->isInstantiationDependent() || E->getType()->isScalarType())) {
+          if (!X->isLValue()) {
+            ErrorFound = NotAnLValue;
+            ErrorLoc = AtomicBinOp->getExprLoc();
+            ErrorRange = AtomicBinOp->getSourceRange();
+            NoteLoc = X->getExprLoc();
+            NoteRange = X->getSourceRange();
+          }
+        } else if (!X->isInstantiationDependent() ||
+                   !E->isInstantiationDependent()) {
+          auto NotScalarExpr =
+              (X->isInstantiationDependent() || X->getType()->isScalarType())
+                  ? E
+                  : X;
+          ErrorFound = NotAScalarType;
+          ErrorLoc = AtomicBinOp->getExprLoc();
+          ErrorRange = AtomicBinOp->getSourceRange();
+          NoteLoc = NotScalarExpr->getExprLoc();
+          NoteRange = NotScalarExpr->getSourceRange();
+        }
+      } else {
+        ErrorFound = NotAnAssignmentOp;
+        ErrorLoc = AtomicBody->getExprLoc();
+        ErrorRange = AtomicBody->getSourceRange();
+        NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
+                              : AtomicBody->getExprLoc();
+        NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
+                                : AtomicBody->getSourceRange();
+      }
+    } else {
+      ErrorFound = NotAnExpression;
+      NoteLoc = ErrorLoc = Body->getLocStart();
+      NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
     }
+    if (ErrorFound != NoError) {
+      Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
+          << ErrorRange;
+      Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
+                                                      << NoteRange;
+      return StmtError();
+    } else if (CurContext->isDependentContext())
+      E = X = nullptr;
   } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
     if (!isa<Expr>(Body)) {
       Diag(Body->getLocStart(),

Modified: cfe/trunk/test/OpenMP/atomic_messages.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_messages.c?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_messages.c (original)
+++ cfe/trunk/test/OpenMP/atomic_messages.c Fri Nov 28 01:21:40 2014
@@ -63,3 +63,40 @@ int readS() {
 
   return a.a;
 }
+
+int writeint() {
+  int a = 0, b = 0;
+// Test for atomic write
+#pragma omp atomic write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected an expression statement}}
+  ;
+#pragma omp atomic write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected built-in assignment operator}}
+  foo();
+#pragma omp atomic write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected built-in assignment operator}}
+  a += b;
+#pragma omp atomic write
+  a = 0;
+#pragma omp atomic write
+  a = b;
+  // expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
+#pragma omp atomic write write
+  a = b;
+
+  return 0;
+}
+
+int writeS() {
+  struct S a, b;
+  // expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
+#pragma omp atomic write write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected expression of scalar type}}
+  a = b;
+
+  return a.a;
+}

Modified: cfe/trunk/test/OpenMP/atomic_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_messages.cpp?rev=222913&r1=222912&r2=222913&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/atomic_messages.cpp Fri Nov 28 01:21:40 2014
@@ -100,11 +100,24 @@ T write() {
   T a, b = 0;
 // Test for atomic write
 #pragma omp atomic write
-  // expected-error at +1 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is an l-value expression with scalar type}}
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected an expression statement}}
   ;
 // expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
 #pragma omp atomic write write
   a = b;
+#pragma omp atomic write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected built-in assignment operator}}
+  foo();
+#pragma omp atomic write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected built-in assignment operator}}
+  a += b;
+#pragma omp atomic write
+  a = 0;
+#pragma omp atomic write
+  a = b;
 
   return T();
 }
@@ -113,11 +126,24 @@ int write() {
   int a, b = 0;
 // Test for atomic write
 #pragma omp atomic write
-  // expected-error at +1 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is an l-value expression with scalar type}}
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected an expression statement}}
   ;
 // expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
 #pragma omp atomic write write
   a = b;
+#pragma omp atomic write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected built-in assignment operator}}
+  foo();
+#pragma omp atomic write
+  // expected-error at +2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
+  // expected-note at +1 {{expected built-in assignment operator}}
+  a += b;
+#pragma omp atomic write
+  a = 0;
+#pragma omp atomic write
+  a = foo();
 
   return write<int>();
 }





More information about the cfe-commits mailing list