diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3989,6 +3989,7 @@ UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct); std::variant u; + CharBlock source; }; struct OpenACCBlockConstruct { diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp --- a/flang/lib/Parser/openacc-parsers.cpp +++ b/flang/lib/Parser/openacc-parsers.cpp @@ -242,10 +242,11 @@ statement(assignmentStmt), statement(assignmentStmt), Parser{} / endAccLine)) -TYPE_PARSER(construct(Parser{}) || - construct(Parser{}) || - construct(Parser{}) || - construct(Parser{})) +TYPE_PARSER( + sourced(construct(Parser{})) || + sourced(construct(Parser{})) || + sourced(construct(Parser{})) || + sourced(construct(Parser{}))) // 2.13 Declare constructs TYPE_PARSER(sourced(construct( diff --git a/flang/lib/Semantics/check-acc-structure.h b/flang/lib/Semantics/check-acc-structure.h --- a/flang/lib/Semantics/check-acc-structure.h +++ b/flang/lib/Semantics/check-acc-structure.h @@ -55,6 +55,10 @@ void Leave(const parser::OpenACCStandaloneConstruct &); void Enter(const parser::OpenACCStandaloneDeclarativeConstruct &); void Leave(const parser::OpenACCStandaloneDeclarativeConstruct &); + void Enter(const parser::OpenACCWaitConstruct &); + void Leave(const parser::OpenACCWaitConstruct &); + void Enter(const parser::OpenACCAtomicConstruct &); + void Leave(const parser::OpenACCAtomicConstruct &); // Clauses void Leave(const parser::AccClauseList &); diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp --- a/flang/lib/Semantics/check-acc-structure.cpp +++ b/flang/lib/Semantics/check-acc-structure.cpp @@ -256,6 +256,21 @@ dirContext_.pop_back(); } +void AccStructureChecker::Enter(const parser::OpenACCWaitConstruct &x) { + const auto &verbatim{std::get(x.t)}; + PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_wait); +} +void AccStructureChecker::Leave(const parser::OpenACCWaitConstruct &x) { + dirContext_.pop_back(); +} + +void AccStructureChecker::Enter(const parser::OpenACCAtomicConstruct &x) { + PushContextAndClauseSets(x.source, llvm::acc::Directive::ACCD_atomic); +} +void AccStructureChecker::Leave(const parser::OpenACCAtomicConstruct &x) { + dirContext_.pop_back(); +} + // Clause checkers CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(Collapse, ACCC_collapse) diff --git a/flang/test/Semantics/acc-clause-validity.f90 b/flang/test/Semantics/acc-clause-validity.f90 --- a/flang/test/Semantics/acc-clause-validity.f90 +++ b/flang/test/Semantics/acc-clause-validity.f90 @@ -6,6 +6,7 @@ ! 2.5.2 Kernels ! 2.5.3 Serial ! 2.9 Loop +! 2.12 Atomic ! 2.13 Declare ! 2.14.3 Set ! 2.14.4 Update @@ -13,6 +14,7 @@ ! 2.11 Parallel Loop ! 2.11 Kernels Loop ! 2.11 Serial Loop +! 2.16.13 Wait program openacc_clause_validity @@ -414,6 +416,10 @@ !$acc kernels wait(devnum: 1: queues: 1, 2) async(3) !$acc end kernels + !$acc wait + + !$acc wait async + !$acc wait(1) !$acc wait(1, 2) @@ -426,6 +432,46 @@ !$acc wait(devnum: 1: queues: 3) !$acc wait(devnum: 1: queues: 3, 4) + !$acc wait(1) if(.true.) + + !ERROR: At most one IF clause can appear on the WAIT directive + !$acc wait(1) if(.true.) if(.false.) + + !$acc wait(1) if(.true.) async + + !$acc wait(1) if(.true.) async(1) + + !ERROR: At most one ASYNC clause can appear on the WAIT directive + !$acc wait(1) if(.true.) async(1) async + + !$acc parallel + !$acc atomic update + c(i) = c(i) + 1 + + !$acc atomic update + c(i) = c(i) + 1 + !$acc end atomic + + !$acc atomic write + c(i) = 10 + + !$acc atomic write + c(i) = 10 + !$acc end atomic + + !$acc atomic read + i = c(i) + + !$acc atomic read + i = c(i) + !$acc end atomic + + !$acc atomic capture + c(i) = i + i = i + 1 + !$acc end atomic + !$acc end parallel + contains subroutine sub1(a)