[flang-commits] [flang] e43b3b0 - [Flang][OpenMP] Semantic checks for Atomic construct.
Sameeran joshi via flang-commits
flang-commits at lists.llvm.org
Sun Dec 13 23:34:50 PST 2020
Author: sameeran joshi
Date: 2020-12-14T13:03:57+05:30
New Revision: e43b3b08ccd60d63d4c3316859e9fec4cdaeaddd
URL: https://github.com/llvm/llvm-project/commit/e43b3b08ccd60d63d4c3316859e9fec4cdaeaddd
DIFF: https://github.com/llvm/llvm-project/commit/e43b3b08ccd60d63d4c3316859e9fec4cdaeaddd.diff
LOG: [Flang][OpenMP] Semantic checks for Atomic construct.
Patch implements restrictions from 2.17.7 of OpenMP 5.0 standard for atomic Construct. Tests for the same are added.
One of the restriction
`OpenMP constructs may not be encountered during execution of an atomic region.`
Is mentioned in 5.0 standard to be a semantic restriction, but given the stricter nature of parser in F18 it's caught at parsing itself.
This patch is a next patch in series from D88965.
Reviewed By: clementval
Differential Revision: https://reviews.llvm.org/D89583
Added:
flang/test/Semantics/omp-atomic01.f90
Modified:
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/parse-tree.h
flang/lib/Parser/openmp-parsers.cpp
flang/lib/Parser/unparse.cpp
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
flang/test/Semantics/omp-atomic.f90
llvm/include/llvm/Frontend/OpenMP/OMP.td
Removed:
################################################################################
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 791e21fa4b62..0d819f861495 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -551,6 +551,8 @@ class ParseTreeDumper {
NODE(parser, OpenMPDeclareSimdConstruct)
NODE(parser, OpenMPDeclareTargetConstruct)
NODE(parser, OmpMemoryOrderClause)
+ NODE(parser, OmpAtomicClause)
+ NODE(parser, OmpAtomicClauseList)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPLoopConstruct)
NODE(parser, OpenMPExecutableAllocate)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index ca73af210c15..5d2909a4142a 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3628,11 +3628,30 @@ struct OpenMPExecutableAllocate {
t;
};
-// 2.17.7 atomic -> ATOMIC [clause[,]] atomic-clause [[,]clause] |
-// ATOMIC [clause]
-// clause -> memory-order-clause | HINT(hint-expression)
-// memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED
-// atomic-clause -> READ | WRITE | UPDATE | CAPTURE
+// 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0]
+// memory-order-clause -> acq_rel
+// release
+// acquire
+// seq_cst
+// relaxed
+struct OmpMemoryOrderClause {
+ WRAPPER_CLASS_BOILERPLATE(OmpMemoryOrderClause, OmpClause);
+ CharBlock source;
+};
+
+// 2.17.7 Atomic construct
+// atomic-clause -> memory-order-clause | HINT(hint-expression)
+struct OmpAtomicClause {
+ UNION_CLASS_BOILERPLATE(OmpAtomicClause);
+ CharBlock source;
+ std::variant<OmpMemoryOrderClause, OmpClause> u;
+};
+
+// atomic-clause-list -> [atomic-clause, [atomic-clause], ...]
+struct OmpAtomicClauseList {
+ WRAPPER_CLASS_BOILERPLATE(OmpAtomicClauseList, std::list<OmpAtomicClause>);
+ CharBlock source;
+};
// END ATOMIC
EMPTY_CLASS(OmpEndAtomic);
@@ -3641,8 +3660,8 @@ EMPTY_CLASS(OmpEndAtomic);
struct OmpAtomicRead {
TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
CharBlock source;
- std::tuple<OmpClauseList, Verbatim, OmpClauseList, Statement<AssignmentStmt>,
- std::optional<OmpEndAtomic>>
+ std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
+ Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
t;
};
@@ -3650,8 +3669,8 @@ struct OmpAtomicRead {
struct OmpAtomicWrite {
TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
CharBlock source;
- std::tuple<OmpClauseList, Verbatim, OmpClauseList, Statement<AssignmentStmt>,
- std::optional<OmpEndAtomic>>
+ std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
+ Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
t;
};
@@ -3659,8 +3678,8 @@ struct OmpAtomicWrite {
struct OmpAtomicUpdate {
TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
CharBlock source;
- std::tuple<OmpClauseList, Verbatim, OmpClauseList, Statement<AssignmentStmt>,
- std::optional<OmpEndAtomic>>
+ std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
+ Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
t;
};
@@ -3670,7 +3689,8 @@ struct OmpAtomicCapture {
CharBlock source;
WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
- std::tuple<OmpClauseList, Verbatim, OmpClauseList, Stmt1, Stmt2, OmpEndAtomic>
+ std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList, Stmt1, Stmt2,
+ OmpEndAtomic>
t;
};
@@ -3678,11 +3698,15 @@ struct OmpAtomicCapture {
struct OmpAtomic {
TUPLE_CLASS_BOILERPLATE(OmpAtomic);
CharBlock source;
- std::tuple<Verbatim, OmpClauseList, Statement<AssignmentStmt>,
+ std::tuple<Verbatim, OmpAtomicClauseList, Statement<AssignmentStmt>,
std::optional<OmpEndAtomic>>
t;
};
+// 2.17.7 atomic ->
+// ATOMIC [atomic-clause-list] atomic-construct [atomic-clause-list] |
+// ATOMIC [atomic-clause-list]
+// atomic-construct -> READ | WRITE | UPDATE | CAPTURE
struct OpenMPAtomicConstruct {
UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
@@ -3718,14 +3742,6 @@ struct OpenMPCancelConstruct {
std::tuple<Verbatim, OmpCancelType, std::optional<If>> t;
};
-// 2.17.8 Flush Construct [OpenMP 5.0]
-// memory-order-clause -> acq_rel
-// release
-// acquire
-struct OmpMemoryOrderClause {
- WRAPPER_CLASS_BOILERPLATE(OmpMemoryOrderClause, OmpClause);
- CharBlock source;
-};
// 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)]
struct OpenMPFlushConstruct {
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 69fc4f0e67ee..fd209abc4138 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -318,6 +318,18 @@ TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>(
"ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
"RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>())))))
+// 2.17.7 Atomic construct
+// atomic-clause -> memory-order-clause | HINT(hint-expression)
+TYPE_PARSER(sourced(construct<OmpAtomicClause>(
+ construct<OmpAtomicClause>(Parser<OmpMemoryOrderClause>{}) ||
+ construct<OmpAtomicClause>("HINT" >>
+ sourced(construct<OmpClause>(
+ construct<OmpClause::Hint>(parenthesized(constantExpr))))))))
+
+// atomic-clause-list -> [atomic-clause, [atomic-clause], ...]
+TYPE_PARSER(sourced(construct<OmpAtomicClauseList>(
+ many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{})))))
+
TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
maybe(Parser<OmpMemoryOrderClause>{}),
maybe(parenthesized(Parser<OmpObjectList>{})))))
@@ -409,32 +421,32 @@ TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok))
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER("ATOMIC" >>
- construct<OmpAtomicRead>(Parser<OmpClauseList>{} / maybe(","_tok),
- verbatim("READ"_tok), Parser<OmpClauseList>{} / endOmpLine,
+ construct<OmpAtomicRead>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
+ verbatim("READ"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER("ATOMIC" >>
- construct<OmpAtomicCapture>(Parser<OmpClauseList>{} / maybe(","_tok),
- verbatim("CAPTURE"_tok), Parser<OmpClauseList>{} / endOmpLine,
+ construct<OmpAtomicCapture>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
+ verbatim("CAPTURE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
statement(assignmentStmt), statement(assignmentStmt),
Parser<OmpEndAtomic>{} / endOmpLine))
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER("ATOMIC" >>
- construct<OmpAtomicUpdate>(Parser<OmpClauseList>{} / maybe(","_tok),
- verbatim("UPDATE"_tok), Parser<OmpClauseList>{} / endOmpLine,
+ construct<OmpAtomicUpdate>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
+ verbatim("UPDATE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
-// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST]
+// OMP ATOMIC [atomic-clause-list]
TYPE_PARSER(construct<OmpAtomic>(verbatim("ATOMIC"_tok),
- Parser<OmpClauseList>{} / endOmpLine, statement(assignmentStmt),
+ Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER("ATOMIC" >>
- construct<OmpAtomicWrite>(Parser<OmpClauseList>{} / maybe(","_tok),
- verbatim("WRITE"_tok), Parser<OmpClauseList>{} / endOmpLine,
+ construct<OmpAtomicWrite>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
+ verbatim("WRITE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
// Atomic Construct
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index cf843ffb3c9d..c5df6990d102 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2222,10 +2222,12 @@ class UnparseVisitor {
break;
}
}
+ void Unparse(const OmpAtomicClauseList &x) { Walk(" ", x.v, " "); }
+
void Unparse(const OmpAtomic &x) {
BeginOpenMP();
Word("!$OMP ATOMIC");
- Walk(std::get<OmpClauseList>(x.t));
+ Walk(std::get<OmpAtomicClauseList>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<Statement<AssignmentStmt>>(x.t));
@@ -2448,6 +2450,13 @@ class UnparseVisitor {
EndOpenMP();
}
void Unparse(const OmpMemoryOrderClause &x) { Walk(x.v); }
+ void Unparse(const OmpAtomicClause &x) {
+ std::visit(common::visitors{
+ [&](const OmpMemoryOrderClause &y) { Walk(y); },
+ [&](const OmpClause &z) { Walk(z); },
+ },
+ x.u);
+ }
void Unparse(const OpenMPFlushConstruct &x) {
BeginOpenMP();
Word("!$OMP FLUSH ");
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index af76ca5a0a5a..e58e2e509fb8 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -280,6 +280,22 @@ void OmpStructureChecker::Enter(const parser::OmpEndBlockDirective &x) {
}
}
+void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
+ std::visit(
+ common::visitors{
+ [&](const auto &someAtomicConstruct) {
+ const auto &dir{std::get<parser::Verbatim>(someAtomicConstruct.t)};
+ PushContextAndClauseSets(
+ dir.source, llvm::omp::Directive::OMPD_atomic);
+ },
+ },
+ x.u);
+}
+
+void OmpStructureChecker::Leave(const parser::OpenMPAtomicConstruct &) {
+ dirContext_.pop_back();
+}
+
// Clauses
// Mainly categorized as
// 1. Checks on 'OmpClauseList' from 'parse-tree.h'.
@@ -399,6 +415,7 @@ CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire)
CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst)
CHECK_SIMPLE_CLAUSE(Release, OMPC_release)
CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed)
+CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint)
CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator)
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
@@ -468,7 +485,36 @@ CHECK_SIMPLE_PARSER_CLAUSE(OmpDistScheduleClause, OMPC_dist_schedule)
CHECK_SIMPLE_PARSER_CLAUSE(OmpNowait, OMPC_nowait)
CHECK_SIMPLE_PARSER_CLAUSE(OmpProcBindClause, OMPC_proc_bind)
CHECK_SIMPLE_PARSER_CLAUSE(OmpReductionClause, OMPC_reduction)
-
+// Atomic-clause
+CHECK_SIMPLE_PARSER_CLAUSE(OmpAtomicRead, OMPC_read)
+CHECK_SIMPLE_PARSER_CLAUSE(OmpAtomicWrite, OMPC_write)
+CHECK_SIMPLE_PARSER_CLAUSE(OmpAtomicUpdate, OMPC_update)
+CHECK_SIMPLE_PARSER_CLAUSE(OmpAtomicCapture, OMPC_capture)
+
+void OmpStructureChecker::Leave(const parser::OmpAtomicRead &) {
+ CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_read,
+ {llvm::omp::Clause::OMPC_release, llvm::omp::Clause::OMPC_acq_rel});
+}
+void OmpStructureChecker::Leave(const parser::OmpAtomicWrite &) {
+ CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_write,
+ {llvm::omp::Clause::OMPC_acquire, llvm::omp::Clause::OMPC_acq_rel});
+}
+void OmpStructureChecker::Leave(const parser::OmpAtomicUpdate &) {
+ CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_update,
+ {llvm::omp::Clause::OMPC_acquire, llvm::omp::Clause::OMPC_acq_rel});
+}
+// OmpAtomic node represents atomic directive without atomic-clause.
+// atomic-clause - READ,WRITE,UPDATE,CAPTURE.
+void OmpStructureChecker::Leave(const parser::OmpAtomic &) {
+ if (const auto *clause{FindClause(llvm::omp::Clause::OMPC_acquire)}) {
+ context_.Say(clause->source,
+ "Clause ACQUIRE is not allowed on the ATOMIC directive"_err_en_US);
+ }
+ if (const auto *clause{FindClause(llvm::omp::Clause::OMPC_acq_rel)}) {
+ context_.Say(clause->source,
+ "Clause ACQ_REL is not allowed on the ATOMIC directive"_err_en_US);
+ }
+}
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpAlignedClause &x) {
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index e2233a1094c9..a5dd9348ce75 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -121,6 +121,8 @@ class OmpStructureChecker
void Leave(const parser::OpenMPCancellationPointConstruct &);
void Enter(const parser::OpenMPCriticalConstruct &);
void Leave(const parser::OpenMPCriticalConstruct &);
+ void Enter(const parser::OpenMPAtomicConstruct &);
+ void Leave(const parser::OpenMPAtomicConstruct &);
void Leave(const parser::OmpClauseList &);
void Enter(const parser::OmpClause &);
@@ -161,7 +163,16 @@ class OmpStructureChecker
void Enter(const parser::OmpClause::Release &);
void Enter(const parser::OmpClause::Acquire &);
void Enter(const parser::OmpClause::Relaxed &);
-
+ void Enter(const parser::OmpClause::Hint &);
+
+ void Enter(const parser::OmpAtomicRead &);
+ void Leave(const parser::OmpAtomicRead &);
+ void Enter(const parser::OmpAtomicWrite &);
+ void Leave(const parser::OmpAtomicWrite &);
+ void Enter(const parser::OmpAtomicUpdate &);
+ void Leave(const parser::OmpAtomicUpdate &);
+ void Enter(const parser::OmpAtomicCapture &);
+ void Leave(const parser::OmpAtomic &);
void Enter(const parser::OmpAlignedClause &);
void Enter(const parser::OmpAllocateClause &);
void Enter(const parser::OmpDefaultClause &);
diff --git a/flang/test/Semantics/omp-atomic.f90 b/flang/test/Semantics/omp-atomic.f90
index 6f48f94331d6..dae0164e3bfa 100644
--- a/flang/test/Semantics/omp-atomic.f90
+++ b/flang/test/Semantics/omp-atomic.f90
@@ -34,6 +34,17 @@
!$omp atomic
a = a + 1
+ !ERROR: expected 'UPDATE'
+ !ERROR: expected 'WRITE'
+ !ERROR: expected 'CAPTURE'
+ !ERROR: expected 'READ'
+ !$omp atomic num_threads(4)
+ a = a + 1
+
+ !ERROR: expected end of line
+ !ERROR: expected end of line
+ !$omp atomic capture num_threads(4)
+ a = a + 1
!$omp atomic relaxed
a = a + 1
diff --git a/flang/test/Semantics/omp-atomic01.f90 b/flang/test/Semantics/omp-atomic01.f90
new file mode 100644
index 000000000000..298f9aec53c2
--- /dev/null
+++ b/flang/test/Semantics/omp-atomic01.f90
@@ -0,0 +1,334 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! Semantic checks for OpenMP 5.0 standard 2.17.7 atomic Construct.
+
+use omp_lib
+ implicit none
+ integer :: i, j = 10, k=-100, a
+! 2.17.7.1
+! Handled inside parser.
+! OpenMP constructs may not be encountered during execution of an atomic region
+
+! 2.17.7.2
+! At most one memory-order-clause may appear on the construct.
+
+!READ
+ !ERROR: At most one SEQ_CST clause can appear on the READ directive
+ !$omp atomic seq_cst seq_cst read
+ i = j
+ !ERROR: At most one SEQ_CST clause can appear on the READ directive
+ !$omp atomic read seq_cst seq_cst
+ i = j
+ !ERROR: At most one SEQ_CST clause can appear on the READ directive
+ !$omp atomic seq_cst read seq_cst
+ i = j
+
+ !ERROR: At most one ACQUIRE clause can appear on the READ directive
+ !$omp atomic acquire acquire read
+ i = j
+ !ERROR: At most one ACQUIRE clause can appear on the READ directive
+ !$omp atomic read acquire acquire
+ i = j
+ !ERROR: At most one ACQUIRE clause can appear on the READ directive
+ !$omp atomic acquire read acquire
+ i = j
+
+ !ERROR: At most one RELAXED clause can appear on the READ directive
+ !$omp atomic relaxed relaxed read
+ i = j
+ !ERROR: At most one RELAXED clause can appear on the READ directive
+ !$omp atomic read relaxed relaxed
+ i = j
+ !ERROR: At most one RELAXED clause can appear on the READ directive
+ !$omp atomic relaxed read relaxed
+ i = j
+
+!UPDATE
+ !ERROR: At most one SEQ_CST clause can appear on the UPDATE directive
+ !$omp atomic seq_cst seq_cst update
+ i = j
+ !ERROR: At most one SEQ_CST clause can appear on the UPDATE directive
+ !$omp atomic update seq_cst seq_cst
+ i = j
+ !ERROR: At most one SEQ_CST clause can appear on the UPDATE directive
+ !$omp atomic seq_cst update seq_cst
+ i = j
+
+ !ERROR: At most one RELEASE clause can appear on the UPDATE directive
+ !$omp atomic release release update
+ i = j
+ !ERROR: At most one RELEASE clause can appear on the UPDATE directive
+ !$omp atomic update release release
+ i = j
+ !ERROR: At most one RELEASE clause can appear on the UPDATE directive
+ !$omp atomic release update release
+ i = j
+
+ !ERROR: At most one RELAXED clause can appear on the UPDATE directive
+ !$omp atomic relaxed relaxed update
+ i = j
+ !ERROR: At most one RELAXED clause can appear on the UPDATE directive
+ !$omp atomic update relaxed relaxed
+ i = j
+ !ERROR: At most one RELAXED clause can appear on the UPDATE directive
+ !$omp atomic relaxed update relaxed
+ i = j
+
+!CAPTURE
+ !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: 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: 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: At most one RELEASE clause can appear on the CAPTURE directive
+ !$omp atomic release release capture
+ i = j
+ j = k
+ !$omp end atomic
+
+ !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: At most one RELEASE clause can appear on the CAPTURE directive
+ !$omp atomic release capture release
+ i = j
+ j = k
+ !$omp end atomic
+
+ !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: At most one RELAXED clause can appear on the CAPTURE directive
+ !$omp atomic capture relaxed relaxed
+ i = j
+ j = k
+ !$omp end atomic
+
+ !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: 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: 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: 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: At most one ACQUIRE clause can appear on the CAPTURE directive
+ !$omp atomic acquire acquire capture
+ i = j
+ j = k
+ !$omp end atomic
+
+ !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: At most one ACQUIRE clause can appear on the CAPTURE directive
+ !$omp atomic acquire capture acquire
+ i = j
+ j = k
+ !$omp end atomic
+
+!WRITE
+ !ERROR: At most one SEQ_CST clause can appear on the WRITE directive
+ !$omp atomic seq_cst seq_cst write
+ i = j
+ !ERROR: At most one SEQ_CST clause can appear on the WRITE directive
+ !$omp atomic write seq_cst seq_cst
+ i = j
+ !ERROR: At most one SEQ_CST clause can appear on the WRITE directive
+ !$omp atomic seq_cst write seq_cst
+ i = j
+
+ !ERROR: At most one RELEASE clause can appear on the WRITE directive
+ !$omp atomic release release write
+ i = j
+ !ERROR: At most one RELEASE clause can appear on the WRITE directive
+ !$omp atomic write release release
+ i = j
+ !ERROR: At most one RELEASE clause can appear on the WRITE directive
+ !$omp atomic release write release
+ i = j
+
+ !ERROR: At most one RELAXED clause can appear on the WRITE directive
+ !$omp atomic relaxed relaxed write
+ i = j
+ !ERROR: At most one RELAXED clause can appear on the WRITE directive
+ !$omp atomic write relaxed relaxed
+ i = j
+ !ERROR: At most one RELAXED clause can appear on the WRITE directive
+ !$omp atomic relaxed write relaxed
+ i = j
+
+!No atomic-clause
+ !ERROR: At most one RELAXED clause can appear on the ATOMIC directive
+ !$omp atomic relaxed relaxed
+ i = j
+ !ERROR: At most one SEQ_CST clause can appear on the ATOMIC directive
+ !$omp atomic seq_cst seq_cst
+ i = j
+ !ERROR: At most one RELEASE clause can appear on the ATOMIC directive
+ !$omp atomic release release
+ i = j
+
+! 2.17.7.3
+! At most one hint clause may appear on the construct.
+
+ !ERROR: At most one HINT clause can appear on the READ directive
+ !$omp atomic hint(omp_sync_hint_speculative) hint(omp_sync_hint_speculative) read
+ i = j
+ !ERROR: At most one HINT clause can appear on the READ directive
+ !$omp atomic hint(omp_sync_hint_nonspeculative) read hint(omp_sync_hint_nonspeculative)
+ i = j
+ !ERROR: At most one HINT clause can appear on the READ directive
+ !$omp atomic read hint(omp_sync_hint_uncontended) hint (omp_sync_hint_uncontended)
+ i = j
+ !ERROR: At most one HINT clause can appear on the WRITE directive
+ !$omp atomic hint(omp_sync_hint_contended) hint(omp_sync_hint_speculative) write
+ i = j
+ !ERROR: At most one HINT clause can appear on the WRITE directive
+ !$omp atomic hint(omp_sync_hint_nonspeculative) write hint(omp_sync_hint_nonspeculative)
+ i = j
+ !ERROR: At most one HINT clause can appear on the WRITE directive
+ !$omp atomic write hint(omp_sync_hint_none) hint (omp_sync_hint_uncontended)
+ i = j
+ !ERROR: At most one HINT clause can appear on the WRITE directive
+ !$omp atomic hint(omp_sync_hint_contended) hint(omp_sync_hint_speculative) write
+ i = j
+ !ERROR: At most one HINT clause can appear on the WRITE directive
+ !$omp atomic hint(omp_sync_hint_nonspeculative) write hint(omp_sync_hint_nonspeculative)
+ i = j
+ !ERROR: At most one HINT clause can appear on the WRITE directive
+ !$omp atomic write hint(omp_sync_hint_none) hint (omp_sync_hint_uncontended)
+ 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
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ i = j
+
+ !ERROR: At most one HINT clause can appear on the CAPTURE directive
+ !$omp atomic hint(omp_sync_hint_contended) hint(omp_sync_hint_speculative) capture
+ i = j
+ j = k
+ !$omp end atomic
+ !ERROR: At most one HINT clause can appear on the CAPTURE directive
+ !$omp atomic hint(omp_sync_hint_nonspeculative) capture hint(omp_sync_hint_nonspeculative)
+ i = j
+ j = k
+ !$omp end atomic
+ !ERROR: At most one HINT clause can appear on the CAPTURE directive
+ !$omp atomic capture hint(omp_sync_hint_none) hint (omp_sync_hint_uncontended)
+ i = j
+ j = k
+ !$omp end atomic
+! 2.17.7.4
+! If atomic-clause is read then memory-order-clause must not be acq_rel or release.
+
+ !ERROR: Clause ACQ_REL is not allowed if clause READ appears on the ATOMIC directive
+ !$omp atomic acq_rel read
+ i = j
+ !ERROR: Clause ACQ_REL is not allowed if clause READ appears on the ATOMIC directive
+ !$omp atomic read acq_rel
+ i = j
+
+ !ERROR: Clause RELEASE is not allowed if clause READ appears on the ATOMIC directive
+ !$omp atomic release read
+ i = j
+ !ERROR: Clause RELEASE is not allowed if clause READ appears on the ATOMIC directive
+ !$omp atomic read release
+ i = j
+
+! 2.17.7.5
+! If atomic-clause is write then memory-order-clause must not be acq_rel or acquire.
+
+ !ERROR: Clause ACQ_REL is not allowed if clause WRITE appears on the ATOMIC directive
+ !$omp atomic acq_rel write
+ i = j
+ !ERROR: Clause ACQ_REL is not allowed if clause WRITE appears on the ATOMIC directive
+ !$omp atomic write acq_rel
+ i = j
+
+ !ERROR: Clause ACQUIRE is not allowed if clause WRITE appears on the ATOMIC directive
+ !$omp atomic acquire write
+ i = j
+ !ERROR: Clause ACQUIRE is not allowed if clause WRITE appears on the ATOMIC directive
+ !$omp atomic write acquire
+ i = j
+
+
+! 2.17.7.6
+! If atomic-clause is update or not present then memory-order-clause must not be acq_rel or acquire.
+
+ !ERROR: Clause ACQ_REL is not allowed if clause UPDATE appears on the ATOMIC directive
+ !$omp atomic acq_rel update
+ i = j
+ !ERROR: Clause ACQ_REL is not allowed if clause UPDATE appears on the ATOMIC directive
+ !$omp atomic update acq_rel
+ i = j
+
+ !ERROR: Clause ACQUIRE is not allowed if clause UPDATE appears on the ATOMIC directive
+ !$omp atomic acquire update
+ i = j
+
+ !ERROR: Clause ACQUIRE is not allowed if clause UPDATE appears on the ATOMIC directive
+ !$omp atomic update acquire
+ i = j
+
+ !ERROR: Clause ACQ_REL is not allowed on the ATOMIC directive
+ !$omp atomic acq_rel
+ i = j
+
+ !ERROR: Clause ACQUIRE is not allowed on the ATOMIC directive
+ !$omp atomic acquire
+ i = j
+end program
+
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 6f16cfe730b7..13aa1381d679 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -468,6 +468,8 @@ def OMP_Atomic : Directive<"atomic"> {
VersionedClause<OMPC_Write>,
VersionedClause<OMPC_Update>,
VersionedClause<OMPC_Capture>,
+ ];
+ let allowedOnceClauses = [
VersionedClause<OMPC_SeqCst>,
VersionedClause<OMPC_AcqRel, 50>,
VersionedClause<OMPC_Acquire, 50>,
More information about the flang-commits
mailing list