[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