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 @@ -187,6 +187,17 @@ void AccStructureChecker::Enter(const parser::OpenACCStandaloneConstruct &x) { const auto &standaloneDir{std::get(x.t)}; PushContextAndClauseSets(standaloneDir.source, standaloneDir.v); + if (standaloneDir.v == llvm::acc::Directive::ACCD_set) { + // Restriction - 2255 Two instances of the same clause may not appear on + // the same directive. + // Since these clauses are already in requiredClauses set, they cannot + // be also in allowedOnceClauses set. The double restriction is enforced + // here. + SetContextAllowedOnce(GetContext().allowedOnceClauses + + llvm::acc::Clause::ACCC_default_async + + llvm::acc::Clause::ACCC_device_num + + llvm::acc::Clause::ACCC_device_type); + } } void AccStructureChecker::Leave(const parser::OpenACCStandaloneConstruct &x) { 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 @@ -14,6 +14,7 @@ ! 2.11 Parallel Loop ! 2.11 Kernels Loop ! 2.11 Serial Loop +! 2.14.3 Set ! 2.16.13 Wait program openacc_clause_validity @@ -42,6 +43,31 @@ !$acc init device_type(2, i, j) !$acc init device_num(i) device_type(i, j) if(ifCondition) + !ERROR: At least one of DEFAULT_ASYNC, DEVICE_NUM, DEVICE_TYPE clause must appear on the SET directive + !$acc set + + !ERROR: At least one of DEFAULT_ASYNC, DEVICE_NUM, DEVICE_TYPE clause must appear on the SET directive + !$acc set if(.TRUE.) + + !ERROR: At most one DEFAULT_ASYNC clause can appear on the SET directive + !$acc set default_async(2) default_async(1) + + !ERROR: At most one DEFAULT_ASYNC clause can appear on the SET directive + !$acc set default_async(2) default_async(1) + + !ERROR: At most one DEVICE_NUM clause can appear on the SET directive + !$acc set device_num(1) device_num(i) + + !ERROR: At most one DEVICE_TYPE clause can appear on the SET directive + !$acc set device_type(i) device_type(2, i, j) + + !$acc set default_async(2) + !$acc set default_async(i) + !$acc set device_num(1) + !$acc set device_num(i) + !$acc set device_type(i) + !$acc set device_type(2, i, j) + !ERROR: At least one of ATTACH, COPYIN, CREATE clause must appear on the ENTER DATA directive !$acc enter data diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td --- a/llvm/include/llvm/Frontend/OpenACC/ACC.td +++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td @@ -415,9 +415,15 @@ // 2.14.3 def ACC_Set : Directive<"set"> { let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause ]; let requiredClauses = [ + // The three following clauses are also in allowedOnceClauses list due to + // restriction 2255 - Two instances of the same clause may not appear on the + // same directive. VersionedClause, VersionedClause, VersionedClause