forked from OSchip/llvm-project
Added OpenMP 5.0 specification based semantic checks for atomic update construct
This commit is contained in:
parent
ea2112ea15
commit
3519dcfec2
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue