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>, _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits