Added OpenMP 5.0 specification based semantic checks for atomic update construct

This commit is contained in:
Nimish Mishra 2022-01-24 10:02:58 +05:30
parent ea2112ea15
commit 3519dcfec2
7 changed files with 600 additions and 4 deletions

View File

@ -1324,13 +1324,163 @@ void OmpStructureChecker::Leave(const parser::OmpEndBlockDirective &x) {
}
}
template <typename T, typename D>
bool OmpStructureChecker::IsOperatorValid(const T &node, const D &variable) {
using AllowedBinaryOperators =
std::variant<parser::Expr::Add, parser::Expr::Multiply,
parser::Expr::Subtract, parser::Expr::Divide, parser::Expr::AND,
parser::Expr::OR, parser::Expr::EQV, parser::Expr::NEQV>;
using BinaryOperators = std::variant<parser::Expr::Add,
parser::Expr::Multiply, parser::Expr::Subtract, parser::Expr::Divide,
parser::Expr::AND, parser::Expr::OR, parser::Expr::EQV,
parser::Expr::NEQV, parser::Expr::Power, parser::Expr::Concat,
parser::Expr::LT, parser::Expr::LE, parser::Expr::EQ, parser::Expr::NE,
parser::Expr::GE, parser::Expr::GT>;
if constexpr (common::HasMember<T, BinaryOperators>) {
const auto &variableName{variable.GetSource().ToString()};
const auto &exprLeft{std::get<0>(node.t)};
const auto &exprRight{std::get<1>(node.t)};
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);
}
return common::HasMember<T, AllowedBinaryOperators>;
}
return true;
}
void OmpStructureChecker::CheckAtomicUpdateAssignmentStmt(
const parser::AssignmentStmt &assignment) {
const auto &expr{std::get<parser::Expr>(assignment.t)};
const auto &var{std::get<parser::Variable>(assignment.t)};
std::visit(
common::visitors{
[&](const common::Indirection<parser::FunctionReference> &x) {
const auto &procedureDesignator{
std::get<parser::ProcedureDesignator>(x.value().v.t)};
const parser::Name *name{
std::get_if<parser::Name>(&procedureDesignator.u)};
if (name &&
!(name->source == "max" || name->source == "min" ||
name->source == "iand" || name->source == "ior" ||
name->source == "ieor")) {
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<Fortran::common::Indirection<
Fortran::parser::Designator>>(&var.u)) {
const auto &varDesignator = varDesignatorIndirection->value();
if (const auto *dataRef = std::get_if<Fortran::parser::DataRef>(
&varDesignator.u)) {
if (const auto *name =
std::get_if<Fortran::parser::Name>(&dataRef->u)) {
const auto &varSymbol = *name->symbol;
if (const auto *e{GetExpr(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);
}
},
},
expr.u);
}
void OmpStructureChecker::CheckAtomicMemoryOrderClause(
const parser::OmpAtomicClauseList &clauseList) {
int numMemoryOrderClause = 0;
for (const auto &clause : clauseList.v) {
if (std::get_if<Fortran::parser::OmpMemoryOrderClause>(&clause.u)) {
numMemoryOrderClause++;
if (numMemoryOrderClause > 1) {
context_.Say(clause.source,
"More than one memory order clause not allowed on OpenMP Atomic construct"_err_en_US);
return;
}
}
}
}
void OmpStructureChecker::CheckAtomicMemoryOrderClause(
const parser::OmpAtomicClauseList &leftHandClauseList,
const parser::OmpAtomicClauseList &rightHandClauseList) {
int numMemoryOrderClause = 0;
for (const auto &clause : leftHandClauseList.v) {
if (std::get_if<Fortran::parser::OmpMemoryOrderClause>(&clause.u)) {
numMemoryOrderClause++;
if (numMemoryOrderClause > 1) {
context_.Say(clause.source,
"More than one memory order clause not allowed on OpenMP Atomic construct"_err_en_US);
return;
}
}
}
for (const auto &clause : rightHandClauseList.v) {
if (std::get_if<Fortran::parser::OmpMemoryOrderClause>(&clause.u)) {
numMemoryOrderClause++;
if (numMemoryOrderClause > 1) {
context_.Say(clause.source,
"More than one memory order clause not allowed on OpenMP Atomic construct"_err_en_US);
return;
}
}
}
}
void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
std::visit(
common::visitors{
[&](const auto &someAtomicConstruct) {
const auto &dir{std::get<parser::Verbatim>(someAtomicConstruct.t)};
[&](const parser::OmpAtomic &atomicConstruct) {
const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
PushContextAndClauseSets(
dir.source, llvm::omp::Directive::OMPD_atomic);
CheckAtomicUpdateAssignmentStmt(
std::get<parser::Statement<parser::AssignmentStmt>>(
atomicConstruct.t)
.statement);
CheckAtomicMemoryOrderClause(
std::get<parser::OmpAtomicClauseList>(atomicConstruct.t));
},
[&](const parser::OmpAtomicUpdate &atomicConstruct) {
const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
PushContextAndClauseSets(
dir.source, llvm::omp::Directive::OMPD_atomic);
CheckAtomicUpdateAssignmentStmt(
std::get<parser::Statement<parser::AssignmentStmt>>(
atomicConstruct.t)
.statement);
CheckAtomicMemoryOrderClause(
std::get<0>(atomicConstruct.t), std::get<2>(atomicConstruct.t));
},
[&](const auto &atomicConstruct) {
const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
PushContextAndClauseSets(
dir.source, llvm::omp::Directive::OMPD_atomic);
CheckAtomicMemoryOrderClause(
std::get<0>(atomicConstruct.t), std::get<2>(atomicConstruct.t));
},
},
x.u);

View File

@ -229,6 +229,12 @@ private:
void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
void CheckAtomicMemoryOrderClause(
const parser::OmpAtomicClauseList &, const parser::OmpAtomicClauseList &);
void CheckAtomicMemoryOrderClause(const parser::OmpAtomicClauseList &);
void CheckAtomicUpdateAssignmentStmt(const parser::AssignmentStmt &);
void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct &);
void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
void CheckSIMDNest(const parser::OpenMPConstruct &x);
void CheckTargetNest(const parser::OpenMPConstruct &x);

View File

@ -12,152 +12,184 @@ use omp_lib
! At most one memory-order-clause may appear on the construct.
!READ
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one SEQ_CST clause can appear on the READ directive
!$omp atomic seq_cst seq_cst read
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 READ directive
!$omp atomic read seq_cst seq_cst
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 READ directive
!$omp atomic seq_cst read seq_cst
i = j
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQUIRE clause can appear on the READ directive
!$omp atomic acquire acquire read
i = j
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQUIRE clause can appear on the READ directive
!$omp atomic read acquire acquire
i = j
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQUIRE clause can appear on the READ directive
!$omp atomic acquire read acquire
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 READ directive
!$omp atomic relaxed relaxed read
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 READ directive
!$omp atomic read relaxed relaxed
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 READ directive
!$omp atomic relaxed read relaxed
i = j
!UPDATE
!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
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
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
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
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
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
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
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
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
i = j
!CAPTURE
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one SEQ_CST clause can appear on the CAPTURE directive
!$omp atomic seq_cst seq_cst capture
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one SEQ_CST clause can appear on the CAPTURE directive
!$omp atomic capture seq_cst seq_cst
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one SEQ_CST clause can appear on the CAPTURE directive
!$omp atomic seq_cst capture seq_cst
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one RELEASE clause can appear on the CAPTURE directive
!$omp atomic release release capture
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one RELEASE clause can appear on the CAPTURE directive
!$omp atomic capture release release
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one RELEASE clause can appear on the CAPTURE directive
!$omp atomic release capture release
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one RELAXED clause can appear on the CAPTURE directive
!$omp atomic relaxed relaxed capture
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one RELAXED clause can appear on the CAPTURE directive
!$omp atomic capture relaxed relaxed
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one RELAXED clause can appear on the CAPTURE directive
!$omp atomic relaxed capture relaxed
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQ_REL clause can appear on the CAPTURE directive
!$omp atomic acq_rel acq_rel capture
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQ_REL clause can appear on the CAPTURE directive
!$omp atomic capture acq_rel acq_rel
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQ_REL clause can appear on the CAPTURE directive
!$omp atomic acq_rel capture acq_rel
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQUIRE clause can appear on the CAPTURE directive
!$omp atomic acquire acquire capture
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQUIRE clause can appear on the CAPTURE directive
!$omp atomic capture acquire acquire
i = j
j = k
!$omp end atomic
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one ACQUIRE clause can appear on the CAPTURE directive
!$omp atomic acquire capture acquire
i = j
@ -165,43 +197,55 @@ use omp_lib
!$omp end atomic
!WRITE
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!ERROR: At most one SEQ_CST clause can appear on the WRITE directive
!$omp atomic seq_cst seq_cst write
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 WRITE directive
!$omp atomic write seq_cst seq_cst
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 WRITE directive
!$omp atomic seq_cst write seq_cst
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 WRITE directive
!$omp atomic release release write
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 WRITE directive
!$omp atomic write release release
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 WRITE directive
!$omp atomic release write release
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 WRITE directive
!$omp atomic relaxed relaxed write
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 WRITE directive
!$omp atomic write relaxed relaxed
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 WRITE directive
!$omp atomic relaxed write relaxed
i = j
!No atomic-clause
!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
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
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
i = j

View File

@ -0,0 +1,109 @@
! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp
! OpenMP Atomic construct
! section 2.17.7
! operator is one of +, *, -, /, .AND., .OR., .EQV., or .NEQV
program OmpAtomic
use omp_lib
CHARACTER c*3, d*3
LOGICAL l, m, n
a = 1
b = 2
c = 'foo'
d = 'bar'
m = .TRUE.
n = .FALSE.
!$omp parallel num_threads(4)
!$omp atomic
a = a + (4*2)
!$omp atomic
a = a*(b + 1)
!$omp atomic
a = a - 3
!$omp atomic
a = a/(b + 1)
!$omp atomic
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
a = a**4
!$omp atomic
!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: 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: 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: 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: 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: 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement
l = a .GT. b
!$omp atomic
m = m .AND. n
!$omp atomic
m = m .OR. n
!$omp atomic
m = m .EQV. n
!$omp atomic
m = m .NEQV. n
!$omp atomic update
a = a + (4*2)
!$omp atomic update
a = a*(b + 1)
!$omp atomic update
a = a - 3
!$omp atomic update
a = a/(b + 1)
!$omp atomic update
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
a = a**4
!$omp atomic update
!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: 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: 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: 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: 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: Invalid operator in OpenMP ATOMIC (UPDATE) statement
l = a .GT. b
!$omp atomic update
m = m .AND. n
!$omp atomic update
m = m .OR. n
!$omp atomic update
m = m .EQV. n
!$omp atomic update
m = m .NEQV. n
!$omp end parallel
end program OmpAtomic

View File

@ -0,0 +1,93 @@
! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp
! OpenMP Atomic construct
! section 2.17.7
! Intrinsic procedure name is one of MAX, MIN, IAND, IOR, or IEOR.
program OmpAtomic
use omp_lib
real x
integer :: y, z, a, b, c, d
x = 5.73
y = 3
z = 1
!$omp atomic
y = IAND(y, 4)
!$omp atomic
y = IOR(y, 5)
!$omp atomic
y = IEOR(y, 6)
!$omp atomic
y = MAX(y, 7)
!$omp atomic
y = MIN(y, 8)
!$omp atomic
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = IAND(y, 4)
!$omp atomic
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = IOR(y, 5)
!$omp atomic
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = IEOR(y, 6)
!$omp atomic
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = MAX(y, 7, b, c)
!$omp atomic
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = MIN(y, 8, a, d)
!$omp atomic
!ERROR: Invalid intrinsic procedure name in OpenMP ATOMIC (UPDATE) statement
y = FRACTION(x)
!$omp atomic
!ERROR: Invalid intrinsic procedure name in OpenMP ATOMIC (UPDATE) statement
y = REAL(x)
!$omp atomic update
y = IAND(y, 4)
!$omp atomic update
y = IOR(y, 5)
!$omp atomic update
y = IEOR(y, 6)
!$omp atomic update
y = MAX(y, 7)
!$omp atomic update
y = MIN(y, 8)
!$omp atomic update
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = IAND(y, 4)
!$omp atomic update
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = IOR(y, 5)
!$omp atomic update
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = IEOR(y, 6)
!$omp atomic update
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = MAX(y, 7)
!$omp atomic update
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = MIN(y, 8)
!$omp atomic update
!ERROR: Invalid intrinsic procedure name in OpenMP ATOMIC (UPDATE) statement
y = MOD(y, 9)
!$omp atomic update
!ERROR: Invalid intrinsic procedure name in OpenMP ATOMIC (UPDATE) statement
x = ABS(x)
end program OmpAtomic
subroutine conflicting_types()
type simple
integer :: z
end type
real x
integer :: y, z
type(simple) ::s
z = 1
!$omp atomic
!ERROR: Atomic update variable 'z' not found in the argument list of intrinsic procedure
z = IAND(s%z, 4)
end subroutine

View File

@ -0,0 +1,168 @@
! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp
! OpenMP Atomic construct
! section 2.17.7
! Update assignment must be 'var = var op expr' or 'var = expr op var'
program OmpAtomic
use omp_lib
real x
integer y
logical m, n, l
x = 5.73
y = 3
m = .TRUE.
n = .FALSE.
!$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
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
!$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
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
!$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
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
!$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
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
!$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
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
m = n .OR. l
!$omp atomic
m = m .EQV. n
!$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
m = n .EQV. l
!$omp atomic
m = m .NEQV. n
!$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
m = n .NEQV. l
!$omp atomic update
x = x + 1
!$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
!$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
!$omp atomic update
x = x - 1
!$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
!$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
!$omp atomic update
x = x*1
!$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
!$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
!$omp atomic update
x = x/1
!$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
!$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
!$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
m = n .AND. l
!$omp atomic update
m = m .OR. n
!$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
m = n .OR. l
!$omp atomic update
m = m .EQV. n
!$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
m = n .EQV. l
!$omp atomic update
m = m .NEQV. n
!$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
m = n .NEQV. l
end program OmpAtomic

View File

@ -0,0 +1,26 @@
! RUN: %python %S/test_errors.py %s %flang -fopenmp
! This tests the various semantics related to the clauses of various OpenMP atomic constructs
program OmpAtomic
use omp_lib
integer :: g, x
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!$omp atomic relaxed, seq_cst
x = x + 1
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!$omp atomic read seq_cst, relaxed
x = g
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!$omp atomic write relaxed, release
x = 2 * 4
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!$omp atomic update release, seq_cst
x = 10
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
!$omp atomic capture release, seq_cst
x = g
g = x * 10
!$omp end atomic
end program OmpAtomic