diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1474,22 +1474,27 @@ 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; } - return true; + return false; } void OmpStructureChecker::CheckAtomicUpdateAssignmentStmt( const parser::AssignmentStmt &assignment) { const auto &expr{std::get(assignment.t)}; const auto &var{std::get(assignment.t)}; + bool isIntrinsicProcedure{false}; // whether the atomic update statement + // involves an intrinsic procedure + bool isValidOperator{false}; // whether the `operator` used in the assignemnt + // statement is valid common::visit( common::visitors{ [&](const common::Indirection &x) { + isIntrinsicProcedure = true; const auto &procedureDesignator{ std::get(x.value().v.t)}; const parser::Name *name{ @@ -1501,45 +1506,60 @@ context_.Say(expr.source, "Invalid intrinsic procedure name in " "OpenMP ATOMIC (UPDATE) statement"_err_en_US); - } else if (name) { - bool foundMatch{false}; - if (auto varDesignatorIndirection = - std::get_if>(&var.u)) { - const auto &varDesignator = varDesignatorIndirection->value(); - if (const auto *dataRef = std::get_if( - &varDesignator.u)) { - if (const auto *name = - std::get_if(&dataRef->u)) { - const auto &varSymbol = *name->symbol; - if (const auto *e{GetExpr(context_, expr)}) { - for (const Symbol &symbol : - evaluate::CollectSymbols(*e)) { - if (symbol == varSymbol) { - foundMatch = true; - break; - } - } - } - } - } - } - if (!foundMatch) { - context_.Say(expr.source, - "Atomic update variable '%s' not found in the " - "argument list of intrinsic procedure"_err_en_US, - var.GetSource().ToString()); - } } }, [&](const auto &x) { if (!IsOperatorValid(x, var)) { context_.Say(expr.source, - "Invalid operator in OpenMP ATOMIC (UPDATE) statement"_err_en_US); - } + "Invalid or missing operator in atomic update statement"_err_en_US); + } else + isValidOperator = true; }, }, expr.u); + + if (const auto *e{GetExpr(context_, expr)}) { + const auto *v{GetExpr(context_, var)}; + if (e->Rank() != 0) + context_.Say(expr.source, + "Expected scalar expression " + "on the RHS of atomic update assignment " + "statement"_err_en_US); + if (v->Rank() != 0) + context_.Say(var.GetSource(), + "Expected scalar variable " + "on the LHS of atomic update assignment " + "statement"_err_en_US); + const Symbol &varSymbol = evaluate::GetSymbolVector(*v).front(); + int numOfSymbolMatches{0}; + SymbolVector exprSymbols = evaluate::GetSymbolVector(*e); + for (const Symbol &symbol : exprSymbols) { + if (varSymbol == symbol) + numOfSymbolMatches++; + } + if (isIntrinsicProcedure) { + std::string varName = var.GetSource().ToString(); + if (numOfSymbolMatches != 1) + context_.Say(expr.source, + "Intrinsic procedure" + " arguments in atomic update statement" + " must have exactly one occurence of '%s'"_err_en_US, + varName); + else if (varSymbol != exprSymbols.front() && + varSymbol != exprSymbols.back()) + context_.Say(expr.source, + "Atomic update statement " + "should be of the form `%s = intrinsic_procedure(%s, expr_list)` " + "OR `%s = intrinsic_procedure(expr_list, %s)`"_err_en_US, + varName, varName, varName, varName); + } else if (isValidOperator) { + if (numOfSymbolMatches != 1) + context_.Say(expr.source, + "Exactly one occurence of '%s' " + "expected on the RHS of atomic update assignment statement"_err_en_US, + var.GetSource().ToString()); + } + } } void OmpStructureChecker::CheckAtomicMemoryOrderClause( diff --git a/flang/test/Semantics/OpenMP/omp-atomic01.f90 b/flang/test/Semantics/OpenMP/omp-atomic01.f90 --- a/flang/test/Semantics/OpenMP/omp-atomic01.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic01.f90 @@ -55,40 +55,49 @@ !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one SEQ_CST clause can appear on the UPDATE directive !$omp atomic seq_cst seq_cst update + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one SEQ_CST clause can appear on the UPDATE directive !$omp atomic update seq_cst seq_cst + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one SEQ_CST clause can appear on the UPDATE directive !$omp atomic seq_cst update seq_cst + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELEASE clause can appear on the UPDATE directive !$omp atomic release release update + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELEASE clause can appear on the UPDATE directive !$omp atomic update release release + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELEASE clause can appear on the UPDATE directive !$omp atomic release update release + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELAXED clause can appear on the UPDATE directive !$omp atomic relaxed relaxed update + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELAXED clause can appear on the UPDATE directive !$omp atomic update relaxed relaxed + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELAXED clause can appear on the UPDATE directive !$omp atomic relaxed update relaxed + !ERROR: Invalid or missing operator in atomic update statement i = j !CAPTURE @@ -240,14 +249,17 @@ !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELAXED clause can appear on the ATOMIC directive !$omp atomic relaxed relaxed + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one SEQ_CST clause can appear on the ATOMIC directive !$omp atomic seq_cst seq_cst + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !ERROR: At most one RELEASE clause can appear on the ATOMIC directive !$omp atomic release release + !ERROR: Invalid or missing operator in atomic update statement i = j ! 2.17.7.3 @@ -282,21 +294,27 @@ i = j !ERROR: At most one HINT clause can appear on the UPDATE directive !$omp atomic hint(omp_sync_hint_contended) hint(omp_sync_hint_speculative) update + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: At most one HINT clause can appear on the UPDATE directive !$omp atomic hint(omp_sync_hint_nonspeculative) update hint(omp_sync_hint_nonspeculative) + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: At most one HINT clause can appear on the UPDATE directive !$omp atomic update hint(omp_sync_hint_none) hint (omp_sync_hint_uncontended) + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: At most one HINT clause can appear on the ATOMIC directive !$omp atomic hint(omp_sync_hint_contended) hint(omp_sync_hint_speculative) + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: At most one HINT clause can appear on the ATOMIC directive !$omp atomic hint(omp_sync_hint_none) hint(omp_sync_hint_nonspeculative) + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: At most one HINT clause can appear on the ATOMIC directive !$omp atomic hint(omp_sync_hint_none) hint (omp_sync_hint_uncontended) + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: At most one HINT clause can appear on the CAPTURE directive @@ -354,25 +372,31 @@ !ERROR: Clause ACQ_REL is not allowed if clause UPDATE appears on the ATOMIC directive !$omp atomic acq_rel update + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: Clause ACQ_REL is not allowed if clause UPDATE appears on the ATOMIC directive !$omp atomic update acq_rel + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: Clause ACQUIRE is not allowed if clause UPDATE appears on the ATOMIC directive !$omp atomic acquire update + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: Clause ACQUIRE is not allowed if clause UPDATE appears on the ATOMIC directive !$omp atomic update acquire + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: Clause ACQ_REL is not allowed on the ATOMIC directive !$omp atomic acq_rel + !ERROR: Invalid or missing operator in atomic update statement i = j !ERROR: Clause ACQUIRE is not allowed on the ATOMIC directive !$omp atomic acquire + !ERROR: Invalid or missing operator in atomic update statement i = j end program diff --git a/flang/test/Semantics/OpenMP/omp-atomic02.f90 b/flang/test/Semantics/OpenMP/omp-atomic02.f90 --- a/flang/test/Semantics/OpenMP/omp-atomic02.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic02.f90 @@ -26,34 +26,34 @@ !$omp atomic a = a/(b + 1) !$omp atomic - !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Invalid or missing operator in atomic update statement a = a**4 !$omp atomic - !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in atomic update statement l = a .GT. b !$omp atomic m = m .AND. n @@ -72,30 +72,30 @@ !$omp atomic update a = a/(b + 1) !$omp atomic update - !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Invalid or missing operator in atomic update statement a = a**4 !$omp atomic update - !ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement + !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` + !ERROR: Invalid or missing operator in atomic update statement l = a .GT. b !$omp atomic update m = m .AND. n diff --git a/flang/test/Semantics/OpenMP/omp-atomic03.f90 b/flang/test/Semantics/OpenMP/omp-atomic03.f90 --- a/flang/test/Semantics/OpenMP/omp-atomic03.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic03.f90 @@ -23,26 +23,28 @@ y = MIN(y, 8) !$omp atomic - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = IAND(y, 4) !$omp atomic - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = IOR(y, 5) !$omp atomic - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = IEOR(y, 6) !$omp atomic - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = MAX(y, 7, b, c) !$omp atomic - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = MIN(y, 8, a, d) !$omp atomic !ERROR: Invalid intrinsic procedure name in OpenMP ATOMIC (UPDATE) statement + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'y' y = FRACTION(x) !$omp atomic !ERROR: Invalid intrinsic procedure name in OpenMP ATOMIC (UPDATE) statement + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'y' y = REAL(x) !$omp atomic update y = IAND(y, 4) @@ -56,19 +58,19 @@ y = MIN(y, 8) !$omp atomic update - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = IAND(y, 4) -!$omp atomic update - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure +!$omp atomic update + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = IOR(y, 5) !$omp atomic update - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = IEOR(y, 6) !$omp atomic update - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = MAX(y, 7) !$omp atomic update - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = MIN(y, 8) !$omp atomic update @@ -88,6 +90,53 @@ type(simple) ::s z = 1 !$omp atomic - !ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'z' z = IAND(s%z, 4) end subroutine + +subroutine more_invalid_atomic_update_stmts() + integer :: a, b + integer :: k(10) + type some_type + integer :: m(10) + end type + type(some_type) :: s + + !$omp atomic update + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'a' + a = min(a, a, b) + + !$omp atomic + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'a' + a = max(b, a, b, a) + + !$omp atomic + !ERROR: Atomic update statement should be of the form `a = intrinsic_procedure(a, expr_list)` OR `a = intrinsic_procedure(expr_list, a)` + a = min(b, a, b) + + !$omp atomic + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'a' + a = max(b, a, b, a, b) + + !$omp atomic update + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'y' + y = min(z) + + !$omp atomic + z = max(z) + + !$omp atomic update + !ERROR: Expected scalar variable on the LHS of atomic update assignment statement + !ERROR: Intrinsic procedure arguments in atomic update statement must have exactly one occurence of 'k' + k = max(x) + + !$omp atomic + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar REAL(4) and rank 1 array of REAL(4) + !ERROR: Expected scalar expression on the RHS of atomic update assignment statement + x = min(x, k) + + !$omp atomic + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar REAL(4) and rank 1 array of REAL(4) + !ERROR: Expected scalar expression on the RHS of atomic update assignment statement + z =z + s%m +end subroutine diff --git a/flang/test/Semantics/OpenMP/omp-atomic04.f90 b/flang/test/Semantics/OpenMP/omp-atomic04.f90 --- a/flang/test/Semantics/OpenMP/omp-atomic04.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic04.f90 @@ -18,10 +18,12 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1 + y !$omp atomic @@ -29,10 +31,12 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1 - y !$omp atomic @@ -40,10 +44,12 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1*y !$omp atomic @@ -51,26 +57,30 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1/y !$omp atomic m = m .AND. n !$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 +!$omp atomic + !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .AND. l !$omp atomic m = m .OR. n !$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 +!$omp atomic + !ERROR: Atomic update statement should be of form `m = m operator expr` OR `m = expr operator m` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .OR. l !$omp atomic @@ -78,7 +88,8 @@ !$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` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .EQV. l !$omp atomic @@ -86,7 +97,8 @@ !$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` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .NEQV. l !$omp atomic update @@ -94,10 +106,12 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1 + y !$omp atomic update @@ -105,10 +119,12 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1 - y !$omp atomic update @@ -116,10 +132,12 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1*y !$omp atomic update @@ -127,10 +145,12 @@ !$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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement 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` + !ERROR: Exactly one occurence of 'x' expected on the RHS of atomic update assignment statement x = 1/y !$omp atomic update @@ -138,7 +158,8 @@ !$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` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .AND. l !$omp atomic update @@ -146,7 +167,8 @@ !$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` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .OR. l !$omp atomic update @@ -154,7 +176,8 @@ !$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` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .EQV. l !$omp atomic update @@ -162,7 +185,79 @@ !$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` + !ERROR: Exactly one occurence of 'm' expected on the RHS of atomic update assignment statement m = n .NEQV. l end program OmpAtomic + +subroutine more_invalid_atomic_update_stmts() + integer :: a, b, c + integer :: d(10) + real :: x, y, z(10) + type some_type + real :: m + real :: n(10) + end type + type(some_type) p + + !$omp atomic + !ERROR: Invalid or missing operator in atomic update statement + x = x + + !$omp atomic update + !ERROR: Invalid or missing operator in atomic update statement + x = 1 + + !$omp atomic update + !ERROR: Exactly one occurence of 'a' expected on the RHS of atomic update assignment statement + a = a * b + a + + !$omp atomic + !ERROR: Atomic update statement should be of form `a = a operator expr` OR `a = expr operator a` + a = b * (a + 9) + + !$omp atomic update + !ERROR: Exactly one occurence of 'a' expected on the RHS of atomic update assignment statement + a = a * (a + b) + + !$omp atomic + !ERROR: Exactly one occurence of 'a' expected on the RHS of atomic update assignment statement + a = (b + a) * a + + !$omp atomic + !ERROR: Atomic update statement should be of form `a = a operator expr` OR `a = expr operator a` + a = a * b + c + + !$omp atomic update + !ERROR: Atomic update statement should be of form `a = a operator expr` OR `a = expr operator a` + a = a + b + c + + !$omp atomic + a = b * c + a + + !$omp atomic update + a = c + b + a + + !$omp atomic + !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 update assignment statement + a = a + d + + !$omp atomic update + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar REAL(4) and rank 1 array of REAL(4) + !ERROR: Atomic update statement should be of form `x = x operator expr` OR `x = expr operator x` + !ERROR: Expected scalar expression on the RHS of atomic update assignment statement + x = x * y / z + + !$omp atomic + !ERROR: Atomic update statement should be of form `p%m = p%m operator expr` OR `p%m = expr operator p%m` + !ERROR: Exactly one occurence of 'p%m' expected on the RHS of atomic update assignment statement + p%m = x + y + + !$omp atomic update + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar REAL(4) and rank 1 array of REAL(4) + !ERROR: Expected scalar expression on the RHS of atomic update assignment statement + !ERROR: Exactly one occurence of 'p%m' expected on the RHS of atomic update assignment statement + p%m = p%m + p%n +end subroutine diff --git a/flang/test/Semantics/OpenMP/omp-atomic05.f90 b/flang/test/Semantics/OpenMP/omp-atomic05.f90 --- a/flang/test/Semantics/OpenMP/omp-atomic05.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic05.f90 @@ -17,6 +17,7 @@ x = 2 * 4 !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !$omp atomic update release, seq_cst + !ERROR: Invalid or missing operator in atomic update statement x = 10 !ERROR: More than one memory order clause not allowed on OpenMP Atomic construct !$omp atomic capture release, seq_cst