[flang-commits] [flang] 1c4c9e8 - [flang][OpenMP] Added semantic checks for atomic capture, write, and update statements

Nimish Mishra via flang-commits flang-commits at lists.llvm.org
Sat Aug 26 20:47:24 PDT 2023


Author: Nimish Mishra
Date: 2023-08-27T03:44:40Z
New Revision: 1c4c9e8e702956f22dc29f11fec4fd7f6a0ce816

URL: https://github.com/llvm/llvm-project/commit/1c4c9e8e702956f22dc29f11fec4fd7f6a0ce816
DIFF: https://github.com/llvm/llvm-project/commit/1c4c9e8e702956f22dc29f11fec4fd7f6a0ce816.diff

LOG: [flang][OpenMP] Added semantic checks for atomic capture, write, and update statements

This patch adds general checks for atomic read, write, and capture statements.

-check "capture statement is of the form v = x if atomic construct is read"
-check "write statement is of the form x = expr if atomic construct is write"
-check "x must not have the ALLOCATABLE attribute."
-check for non-scalar variables
-check if x (LHS variable) is accessed on the RHS of assignment statement
-improve error reporting in atomic update statemen

Reviewed By: TIFitis, raghavendhra

Differential Revision: https://reviews.llvm.org/D127620

Added: 
    flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90

Modified: 
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/test/Semantics/OpenMP/atomic-hint-clause.f90
    flang/test/Semantics/OpenMP/atomic02.f90
    flang/test/Semantics/OpenMP/atomic04.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 92706aeac9c717..5523dc939696a0 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1647,6 +1647,67 @@ void OmpStructureChecker::Leave(const parser::OmpEndBlockDirective &x) {
   }
 }
 
+inline void OmpStructureChecker::ErrIfAllocatableVariable(
+    const parser::Variable &var) {
+  // Err out if the given symbol has
+  // ALLOCATABLE attribute
+  if (const auto *e{GetExpr(context_, var)})
+    for (const Symbol &symbol : evaluate::CollectSymbols(*e))
+      if (IsAllocatable(symbol)) {
+        const auto &designator =
+            std::get<common::Indirection<parser::Designator>>(var.u);
+        const auto *dataRef =
+            std::get_if<Fortran::parser::DataRef>(&designator.value().u);
+        const Fortran::parser::Name *name =
+            dataRef ? std::get_if<Fortran::parser::Name>(&dataRef->u) : nullptr;
+        if (name)
+          context_.Say(name->source,
+              "%s must not have ALLOCATABLE "
+              "attribute"_err_en_US,
+              name->ToString());
+      }
+}
+
+inline void OmpStructureChecker::ErrIfLHSAndRHSSymbolsMatch(
+    const parser::Variable &var, const parser::Expr &expr) {
+  // Err out if the symbol on the LHS is also used on the RHS of the assignment
+  // statement
+  const auto *e{GetExpr(context_, expr)};
+  const auto *v{GetExpr(context_, var)};
+  if (e && v) {
+    const Symbol &varSymbol = evaluate::GetSymbolVector(*v).front();
+    for (const Symbol &symbol : evaluate::GetSymbolVector(*e)) {
+      if (varSymbol == symbol) {
+        context_.Say(expr.source,
+            "RHS expression "
+            "on atomic assignment statement"
+            " cannot access '%s'"_err_en_US,
+            var.GetSource().ToString());
+      }
+    }
+  }
+}
+
+inline void OmpStructureChecker::ErrIfNonScalarAssignmentStmt(
+    const parser::Variable &var, const parser::Expr &expr) {
+  // Err out if either the variable on the LHS or the expression on the RHS of
+  // the assignment statement are non-scalar (i.e. have rank > 0)
+  const auto *e{GetExpr(context_, expr)};
+  const auto *v{GetExpr(context_, var)};
+  if (e && v) {
+    if (e->Rank() != 0)
+      context_.Say(expr.source,
+          "Expected scalar expression "
+          "on the RHS of atomic assignment "
+          "statement"_err_en_US);
+    if (v->Rank() != 0)
+      context_.Say(var.GetSource(),
+          "Expected scalar variable "
+          "on the LHS of atomic assignment "
+          "statement"_err_en_US);
+  }
+}
+
 template <typename T, typename D>
 bool OmpStructureChecker::IsOperatorValid(const T &node, const D &variable) {
   using AllowedBinaryOperators =
@@ -1667,16 +1728,55 @@ bool OmpStructureChecker::IsOperatorValid(const T &node, const D &variable) {
     if ((exprLeft.value().source.ToString() != variableName) &&
         (exprRight.value().source.ToString() != variableName)) {
       context_.Say(variable.GetSource(),
-          "Atomic update variable '%s' not found in the RHS of the "
-          "assignment statement in an ATOMIC (UPDATE) construct"_err_en_US,
-          variableName);
+          "Atomic update statement should be of form "
+          "`%s = %s operator expr` OR `%s = expr operator %s`"_err_en_US,
+          variableName, variableName, variableName, variableName);
     }
     return common::HasMember<T, AllowedBinaryOperators>;
   }
   return true;
 }
 
-void OmpStructureChecker::CheckAtomicUpdateAssignmentStmt(
+void OmpStructureChecker::CheckAtomicCaptureStmt(
+    const parser::AssignmentStmt &assignmentStmt) {
+  const auto &var{std::get<parser::Variable>(assignmentStmt.t)};
+  const auto &expr{std::get<parser::Expr>(assignmentStmt.t)};
+  common::visit(
+      common::visitors{
+          [&](const common::Indirection<parser::Designator> &designator) {
+            const auto *dataRef =
+                std::get_if<Fortran::parser::DataRef>(&designator.value().u);
+            const auto *name = dataRef
+                ? std::get_if<Fortran::parser::Name>(&dataRef->u)
+                : nullptr;
+            if (name && IsAllocatable(*name->symbol))
+              context_.Say(name->source,
+                  "%s must not have ALLOCATABLE "
+                  "attribute"_err_en_US,
+                  name->ToString());
+          },
+          [&](const auto &) {
+            // Anything other than a `parser::Designator` is not allowed
+            context_.Say(expr.source,
+                "Expected scalar variable "
+                "of intrinsic type on RHS of atomic "
+                "assignment statement"_err_en_US);
+          }},
+      expr.u);
+  ErrIfLHSAndRHSSymbolsMatch(var, expr);
+  ErrIfNonScalarAssignmentStmt(var, expr);
+}
+
+void OmpStructureChecker::CheckAtomicWriteStmt(
+    const parser::AssignmentStmt &assignmentStmt) {
+  const auto &var{std::get<parser::Variable>(assignmentStmt.t)};
+  const auto &expr{std::get<parser::Expr>(assignmentStmt.t)};
+  ErrIfAllocatableVariable(var);
+  ErrIfLHSAndRHSSymbolsMatch(var, expr);
+  ErrIfNonScalarAssignmentStmt(var, expr);
+}
+
+void OmpStructureChecker::CheckAtomicUpdateStmt(
     const parser::AssignmentStmt &assignment) {
   const auto &expr{std::get<parser::Expr>(assignment.t)};
   const auto &var{std::get<parser::Variable>(assignment.t)};
@@ -1734,6 +1834,7 @@ void OmpStructureChecker::CheckAtomicUpdateAssignmentStmt(
           },
       },
       expr.u);
+  ErrIfAllocatableVariable(var);
 }
 
 void OmpStructureChecker::CheckAtomicMemoryOrderClause(
@@ -1772,7 +1873,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
             const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
             PushContextAndClauseSets(
                 dir.source, llvm::omp::Directive::OMPD_atomic);
-            CheckAtomicUpdateAssignmentStmt(
+            CheckAtomicUpdateStmt(
                 std::get<parser::Statement<parser::AssignmentStmt>>(
                     atomicConstruct.t)
                     .statement);
@@ -1787,7 +1888,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
             const auto &dir{std::get<parser::Verbatim>(atomicUpdate.t)};
             PushContextAndClauseSets(
                 dir.source, llvm::omp::Directive::OMPD_atomic);
-            CheckAtomicUpdateAssignmentStmt(
+            CheckAtomicUpdateStmt(
                 std::get<parser::Statement<parser::AssignmentStmt>>(
                     atomicUpdate.t)
                     .statement);
@@ -1796,6 +1897,32 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
             CheckHintClause<const parser::OmpAtomicClauseList>(
                 &std::get<0>(atomicUpdate.t), &std::get<2>(atomicUpdate.t));
           },
+          [&](const parser::OmpAtomicRead &atomicRead) {
+            const auto &dir{std::get<parser::Verbatim>(atomicRead.t)};
+            PushContextAndClauseSets(
+                dir.source, llvm::omp::Directive::OMPD_atomic);
+            CheckAtomicMemoryOrderClause(
+                &std::get<0>(atomicRead.t), &std::get<2>(atomicRead.t));
+            CheckHintClause<const parser::OmpAtomicClauseList>(
+                &std::get<0>(atomicRead.t), &std::get<2>(atomicRead.t));
+            CheckAtomicCaptureStmt(
+                std::get<parser::Statement<parser::AssignmentStmt>>(
+                    atomicRead.t)
+                    .statement);
+          },
+          [&](const parser::OmpAtomicWrite &atomicWrite) {
+            const auto &dir{std::get<parser::Verbatim>(atomicWrite.t)};
+            PushContextAndClauseSets(
+                dir.source, llvm::omp::Directive::OMPD_atomic);
+            CheckAtomicMemoryOrderClause(
+                &std::get<0>(atomicWrite.t), &std::get<2>(atomicWrite.t));
+            CheckHintClause<const parser::OmpAtomicClauseList>(
+                &std::get<0>(atomicWrite.t), &std::get<2>(atomicWrite.t));
+            CheckAtomicWriteStmt(
+                std::get<parser::Statement<parser::AssignmentStmt>>(
+                    atomicWrite.t)
+                    .statement);
+          },
           [&](const auto &atomicConstruct) {
             const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
             PushContextAndClauseSets(

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 7e9c0a80300e26..cdff890ddd417f 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -175,7 +175,9 @@ class OmpStructureChecker
   template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
   void CheckAtomicMemoryOrderClause(
       const parser::OmpAtomicClauseList *, const parser::OmpAtomicClauseList *);
-  void CheckAtomicUpdateAssignmentStmt(const parser::AssignmentStmt &);
+  void CheckAtomicUpdateStmt(const parser::AssignmentStmt &);
+  void CheckAtomicCaptureStmt(const parser::AssignmentStmt &);
+  void CheckAtomicWriteStmt(const parser::AssignmentStmt &);
   void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct &);
   void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
   void CheckSIMDNest(const parser::OpenMPConstruct &x);
@@ -214,7 +216,11 @@ class OmpStructureChecker
   void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
   int GetDirectiveNest(const int index) { return directiveNest_[index]; }
   template <typename D> void CheckHintClause(D *, D *);
-
+  inline void ErrIfAllocatableVariable(const parser::Variable &);
+  inline void ErrIfLHSAndRHSSymbolsMatch(
+      const parser::Variable &, const parser::Expr &);
+  inline void ErrIfNonScalarAssignmentStmt(
+      const parser::Variable &, const parser::Expr &);
   enum directiveNestType {
     SIMDNest,
     TargetBlockOnlyTeams,

diff  --git a/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 b/flang/test/Semantics/OpenMP/atomic-hint-clause.f90
index 048dd978eed56d..3f8fe4953c559f 100644
--- a/flang/test/Semantics/OpenMP/atomic-hint-clause.f90
+++ b/flang/test/Semantics/OpenMP/atomic-hint-clause.f90
@@ -95,6 +95,7 @@ program sample
         x = 10 * y
 
     !$omp atomic write hint(a)
+    !ERROR: RHS expression on atomic assignment statement cannot access 'x'
         x = y + x
 
     !$omp atomic hint(abs(-1)) write

diff  --git a/flang/test/Semantics/OpenMP/atomic02.f90 b/flang/test/Semantics/OpenMP/atomic02.f90
index 336949ada33247..241c27a31dd942 100644
--- a/flang/test/Semantics/OpenMP/atomic02.f90
+++ b/flang/test/Semantics/OpenMP/atomic02.f90
@@ -32,27 +32,27 @@ program OmpAtomic
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    c = c//d
    !$omp atomic
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .LT. b
    !$omp atomic
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .LE. b
    !$omp atomic
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .EQ. b
    !$omp atomic
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .NE. b
    !$omp atomic
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .GE. b
    !$omp atomic
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .GT. b
    !$omp atomic
@@ -78,23 +78,23 @@ program OmpAtomic
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    c = c//d
    !$omp atomic update
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .LT. b
    !$omp atomic update
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .LE. b
    !$omp atomic update
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .EQ. b
    !$omp atomic update
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .GE. b
    !$omp atomic update
-   !ERROR: Atomic update variable 'l' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
    !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
    l = a .GT. b
    !$omp atomic update

diff  --git a/flang/test/Semantics/OpenMP/atomic04.f90 b/flang/test/Semantics/OpenMP/atomic04.f90
index a81a091cdb2254..9ac8ddee884615 100644
--- a/flang/test/Semantics/OpenMP/atomic04.f90
+++ b/flang/test/Semantics/OpenMP/atomic04.f90
@@ -18,21 +18,22 @@ program OmpAtomic
 !$omp atomic
    x = 1 + x
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = y + 1
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
-   x = 1 + y
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
+   x = 1 + (y + x)
 
 !$omp atomic
-   x = x - 1
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
+   x = 1 - (10 * (y + x))
 !$omp atomic
    x = 1 - x
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = y - 1
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = 1 - y
 
 !$omp atomic
@@ -40,21 +41,21 @@ program OmpAtomic
 !$omp atomic
    x = 1*x
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
-   x = y*1
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
+   x = y*(10 + x)
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
-   x = 1*y
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
+   x = (44 * x) * y
 
 !$omp atomic
    x = x/1
 !$omp atomic
    x = 1/x
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = y/1
 !$omp atomic
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = 1/y
 
 !$omp atomic
@@ -62,7 +63,7 @@ program OmpAtomic
 !$omp atomic
    m = n .AND. m
 !$omp atomic
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .AND. l
 
 !$omp atomic
@@ -70,7 +71,7 @@ program OmpAtomic
 !$omp atomic
    m = n .OR. m
 !$omp atomic
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .OR. l
 
 !$omp atomic
@@ -78,7 +79,7 @@ program OmpAtomic
 !$omp atomic
    m = n .EQV. m
 !$omp atomic
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .EQV. l
 
 !$omp atomic
@@ -86,7 +87,7 @@ program OmpAtomic
 !$omp atomic
    m = n .NEQV. m
 !$omp atomic
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .NEQV. l
 
 !$omp atomic update
@@ -94,10 +95,10 @@ program OmpAtomic
 !$omp atomic update
    x = 1 + x
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = y + 1
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = 1 + y
 
 !$omp atomic update
@@ -105,10 +106,10 @@ program OmpAtomic
 !$omp atomic update
    x = 1 - x
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = y - 1
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = 1 - y
 
 !$omp atomic update
@@ -116,10 +117,10 @@ program OmpAtomic
 !$omp atomic update
    x = 1*x
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = y*1
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
    x = 1*y
 
 !$omp atomic update
@@ -127,18 +128,18 @@ program OmpAtomic
 !$omp atomic update
    x = 1/x
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
-   x = y/1
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
+   x = max(x, y) + 10
 !$omp atomic update
-   !ERROR: Atomic update variable 'x' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
-   x = 1/y
+   !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x`
+   x = y * min(x, y)
 
 !$omp atomic update
    m = m .AND. n
 !$omp atomic update
    m = n .AND. m
 !$omp atomic update
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .AND. l
 
 !$omp atomic update
@@ -146,7 +147,7 @@ program OmpAtomic
 !$omp atomic update
    m = n .OR. m
 !$omp atomic update
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .OR. l
 
 !$omp atomic update
@@ -154,7 +155,7 @@ program OmpAtomic
 !$omp atomic update
    m = n .EQV. m
 !$omp atomic update
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .EQV. l
 
 !$omp atomic update
@@ -162,7 +163,7 @@ program OmpAtomic
 !$omp atomic update
    m = n .NEQV. m
 !$omp atomic update
-   !ERROR: Atomic update variable 'm' not found in the RHS of the assignment statement in an ATOMIC (UPDATE) construct
+   !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m`
    m = n .NEQV. l
 
 end program OmpAtomic

diff  --git a/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90
new file mode 100644
index 00000000000000..3ba54a32638b51
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90
@@ -0,0 +1,86 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+! Semantic checks for various assignments related to atomic constructs
+
+program sample
+    use omp_lib
+    integer :: x, v
+    integer :: y(10)
+    integer, allocatable :: k
+    integer a(10)
+    type sample_type
+        integer :: y
+        integer :: m
+    endtype
+    type(sample_type) :: z
+    !$omp atomic read
+        v = x
+
+    !$omp atomic read
+    !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar INTEGER(4) and rank 1 array of INTEGER(4)
+    !ERROR: Expected scalar expression on the RHS of atomic assignment statement
+        v = y(1:3)
+
+    !$omp atomic read
+    !ERROR: Expected scalar variable of intrinsic type on RHS of atomic assignment statement
+        v = x * (10 + x)
+
+    !$omp atomic read
+    !ERROR: Expected scalar variable of intrinsic type on RHS of atomic assignment statement
+        v = 4
+
+    !$omp atomic read
+    !ERROR: k must not have ALLOCATABLE attribute
+        v = k
+
+    !$omp atomic write
+    !ERROR: k must not have ALLOCATABLE attribute
+        k = x
+
+    !$omp atomic update 
+    !ERROR: Atomic update statement should be of form `k = k operator expr` OR `k = expr operator k`
+    !ERROR: k must not have ALLOCATABLE attribute
+        k = v + k * (v * k)
+
+    !$omp atomic
+    !ERROR: k must not have ALLOCATABLE attribute
+        k = v * k  
+         
+    !$omp atomic write
+    !ERROR: RHS expression on atomic assignment statement cannot access 'z%y'
+       z%y = x + z%y
+
+    !$omp atomic write
+    !ERROR: RHS expression on atomic assignment statement cannot access 'x'
+        x = x
+
+    !$omp atomic write
+    !ERROR: RHS expression on atomic assignment statement cannot access 'm'
+        m = min(m, x, z%m) + k
+ 
+    !$omp atomic read
+    !ERROR: RHS expression on atomic assignment statement cannot access 'x'
+        x = x
+
+    !$omp atomic read
+    !ERROR: Expected scalar variable of intrinsic type on RHS of atomic assignment statement
+    !ERROR: RHS expression on atomic assignment statement cannot access 'm'
+        m = min(m, x, z%m) + k
+
+    !$omp atomic read
+    !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar INTEGER(4) and rank 1 array of INTEGER(4)
+    !ERROR: Expected scalar expression on the RHS of atomic assignment statement
+        x = a
+
+    !$omp atomic read
+    !ERROR: Expected scalar variable on the LHS of atomic assignment statement
+        a = x
+
+    !$omp atomic write
+    !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar INTEGER(4) and rank 1 array of INTEGER(4)
+    !ERROR: Expected scalar expression on the RHS of atomic assignment statement
+        x = a
+
+    !$omp atomic write
+    !ERROR: Expected scalar variable on the LHS of atomic assignment statement
+        a = x
+end program


        


More information about the flang-commits mailing list