Index: flang/lib/Semantics/check-omp-structure.h =================================================================== --- flang/lib/Semantics/check-omp-structure.h +++ flang/lib/Semantics/check-omp-structure.h @@ -225,6 +225,8 @@ void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x); void CheckDistLinear(const parser::OpenMPLoopConstruct &x); void CheckSIMDNest(const parser::OpenMPConstruct &x); + void CheckCancellationNest( + const parser::CharBlock &source, const parser::OmpCancelType::Type &type); std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x); void CheckIfDoOrderedClause(const parser::OmpBlockDirective &blkDirectiv); bool CheckReductionOperators(const parser::OmpClause::Reduction &); Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -846,7 +846,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) { const auto &dir{std::get(x.t)}; + const auto &type{std::get(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_cancel); + CheckCancellationNest(dir.source, type.v); } void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) { @@ -867,8 +869,10 @@ void OmpStructureChecker::Enter( const parser::OpenMPCancellationPointConstruct &x) { const auto &dir{std::get(x.t)}; + const auto &type{std::get(x.t)}; PushContextAndClauseSets( dir.source, llvm::omp::Directive::OMPD_cancellation_point); + CheckCancellationNest(dir.source, type.v); } void OmpStructureChecker::Leave( @@ -876,6 +880,62 @@ dirContext_.pop_back(); } +void OmpStructureChecker::CheckCancellationNest( + const parser::CharBlock &source, const parser::OmpCancelType::Type &type) { + if (CurrentDirectiveIsNested()) { + OmpDirectiveSet allowedTaskgroupSet{ + llvm::omp::Directive::OMPD_task, llvm::omp::Directive::OMPD_taskloop}; + OmpDirectiveSet allowedSectionsSet{llvm::omp::Directive::OMPD_sections, + llvm::omp::Directive::OMPD_parallel_sections}; + OmpDirectiveSet allowedDoSet{llvm::omp::Directive::OMPD_do, + llvm::omp::Directive::OMPD_distribute_parallel_do, + llvm::omp::Directive::OMPD_parallel_do, + llvm::omp::Directive::OMPD_target_parallel_do, + llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do, + llvm::omp::Directive::OMPD_teams_distribute_parallel_do}; + OmpDirectiveSet allowedParallelSet{llvm::omp::Directive::OMPD_parallel, + llvm::omp::Directive::OMPD_target_parallel}; + + bool eligibleCancellation{false}; + switch (type) { + case parser::OmpCancelType::Type::Taskgroup: + if (allowedTaskgroupSet.test(GetContextParent().directive)) { + eligibleCancellation = true; + } + break; + case parser::OmpCancelType::Type::Sections: + if (allowedSectionsSet.test(GetContextParent().directive)) { + eligibleCancellation = true; + } + break; + case Fortran::parser::OmpCancelType::Type::Do: + if (allowedDoSet.test(GetContextParent().directive)) { + eligibleCancellation = true; + } + break; + case parser::OmpCancelType::Type::Parallel: + if (allowedParallelSet.test(GetContextParent().directive)) { + eligibleCancellation = true; + } + break; + default: + break; + } + if (!eligibleCancellation) { + context_.Say(source, + "%s %s construct cannot be closely nested inside %s " + "construct"_err_en_US, + ContextDirectiveAsFortran(), + parser::ToUpperCaseLetters(parser::OmpCancelType::EnumToString(type)), + parser::ToUpperCaseLetters( + getDirectiveName(GetContextParent().directive).str())); + } + } else { + context_.Say(source, "orphaned %s directives are prohibited"_err_en_US, + ContextDirectiveAsFortran()); + } +} + void OmpStructureChecker::Enter(const parser::OmpEndBlockDirective &x) { const auto &dir{std::get(x.t)}; ResetPartialContext(dir.source); Index: flang/test/Semantics/omp-clause-validity01.f90 =================================================================== --- flang/test/Semantics/omp-clause-validity01.f90 +++ flang/test/Semantics/omp-clause-validity01.f90 @@ -494,9 +494,6 @@ !ERROR: RELAXED clause is not allowed on the FLUSH directive !$omp flush relaxed - !$omp cancel DO - !$omp cancellation point parallel - ! 2.13.2 critical Construct ! !$omp critical (first) Index: flang/test/Semantics/omp-nested-cancel.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-nested-cancel.f90 @@ -0,0 +1,161 @@ +! RUN: %S/test_errors.sh %s %t %flang -fopenmp +! REQUIRES: shell + +! OpenMP Version 5.0 +! Check OpenMP construct validity for the following directives: +! 2.18.1 Cancel Construct + +program main + integer :: i, N = 10 + real :: a + + !ERROR: orphaned CANCEL directives are prohibited + !$omp cancel taskgroup + + !ERROR: orphaned CANCEL directives are prohibited + !$omp cancel sections + + !ERROR: orphaned CANCEL directives are prohibited + !$omp cancel do + + !ERROR: orphaned CANCEL directives are prohibited + !$omp cancel parallel + + !$omp task + !$omp cancel taskgroup + a = 3.14 + !$omp end task + + !$omp taskloop + do i = 1, N + !$omp parallel + !$omp end parallel + !$omp cancel taskgroup + a = 3.14 + end do + !$omp end taskloop + + !$omp taskloop nogroup + do i = 1, N + !$omp cancel taskgroup + a = 3.14 + end do + + !$omp parallel + !ERROR: CANCEL TASKGROUP construct cannot be closely nested inside PARALLEL construct + !$omp cancel taskgroup + a = 3.14 + !$omp end parallel + + !$omp parallel + !$omp sections + !$omp cancel sections + !$omp section + a = 3.14 + !$omp end sections + !$omp end parallel + + !$omp sections + !$omp section + !$omp cancel sections + a = 3.14 + !$omp end sections + + !$omp parallel + !ERROR: CANCEL SECTIONS construct cannot be closely nested inside PARALLEL construct + !$omp cancel sections + a = 3.14 + !$omp end parallel + + !$omp parallel sections + !$omp cancel sections + a = 3.14 + !$omp end parallel sections + + !$omp do + do i = 1, N + a = 3.14 + !$omp cancel do + end do + !$omp end do + + !$omp parallel do + do i = 1, N + a = 3.14 + !$omp cancel do + end do + !$omp end parallel do + + !$omp target + !$omp teams + !$omp distribute parallel do + do i = 1, N + a = 3.14 + !$omp cancel do + end do + !$omp end distribute parallel do + !$omp end teams + !$omp end target + + !$omp target + !$omp teams distribute parallel do + do i = 1, N + a = 3.14 + !$omp cancel do + end do + !$omp end teams distribute parallel do + !$omp end target + + !$omp target teams distribute parallel do + do i = 1, N + a = 3.14 + !$omp cancel do + end do + !$omp end target teams distribute parallel do + + !$omp target parallel do + do i = 1, N + a = 3.14 + !$omp cancel do + end do + !$omp end target parallel do + + !$omp parallel + do i = 1, N + a = 3.14 + !ERROR: CANCEL DO construct cannot be closely nested inside PARALLEL construct + !$omp cancel do + end do + !$omp end parallel + + !$omp parallel + do i = 1, N + a = 3.14 + !$omp cancel parallel + end do + !$omp end parallel + + !$omp target parallel + do i = 1, N + a = 3.14 + !$omp cancel parallel + end do + !$omp end target parallel + + !$omp target parallel do + do i = 1, N + a = 3.14 + !ERROR: CANCEL PARALLEL construct cannot be closely nested inside TARGET PARALLEL DO construct + !$omp cancel parallel + end do + !$omp end target parallel do + + !$omp do + do i = 1, N + a = 3.14 + !ERROR: CANCEL PARALLEL construct cannot be closely nested inside DO construct + !$omp cancel parallel + end do + !$omp end do + +end program main Index: flang/test/Semantics/omp-nested-cancellation-point.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-nested-cancellation-point.f90 @@ -0,0 +1,161 @@ +! RUN: %S/test_errors.sh %s %t %flang -fopenmp +! REQUIRES: shell + +! OpenMP Version 5.0 +! Check OpenMP construct validity for the following directives: +! 2.18.2 Cancellation Point Construct + +program main + integer :: i, N = 10 + real :: a + + !ERROR: orphaned CANCELLATION POINT directives are prohibited + !$omp cancellation point taskgroup + + !ERROR: orphaned CANCELLATION POINT directives are prohibited + !$omp cancellation point sections + + !ERROR: orphaned CANCELLATION POINT directives are prohibited + !$omp cancellation point do + + !ERROR: orphaned CANCELLATION POINT directives are prohibited + !$omp cancellation point parallel + + !$omp task + !$omp cancellation point taskgroup + a = 3.14 + !$omp end task + + !$omp taskloop + do i = 1, N + !$omp parallel + !$omp end parallel + !$omp cancellation point taskgroup + a = 3.14 + end do + !$omp end taskloop + + !$omp taskloop nogroup + do i = 1, N + !$omp cancellation point taskgroup + a = 3.14 + end do + + !$omp parallel + !ERROR: CANCELLATION POINT TASKGROUP construct cannot be closely nested inside PARALLEL construct + !$omp cancellation point taskgroup + a = 3.14 + !$omp end parallel + + !$omp parallel + !$omp sections + !$omp cancellation point sections + !$omp section + a = 3.14 + !$omp end sections + !$omp end parallel + + !$omp sections + !$omp section + !$omp cancellation point sections + a = 3.14 + !$omp end sections + + !$omp parallel + !ERROR: CANCELLATION POINT SECTIONS construct cannot be closely nested inside PARALLEL construct + !$omp cancellation point sections + a = 3.14 + !$omp end parallel + + !$omp parallel sections + !$omp cancellation point sections + a = 3.14 + !$omp end parallel sections + + !$omp do + do i = 1, N + a = 3.14 + !$omp cancellation point do + end do + !$omp end do + + !$omp parallel do + do i = 1, N + a = 3.14 + !$omp cancellation point do + end do + !$omp end parallel do + + !$omp target + !$omp teams + !$omp distribute parallel do + do i = 1, N + a = 3.14 + !$omp cancellation point do + end do + !$omp end distribute parallel do + !$omp end teams + !$omp end target + + !$omp target + !$omp teams distribute parallel do + do i = 1, N + a = 3.14 + !$omp cancellation point do + end do + !$omp end teams distribute parallel do + !$omp end target + + !$omp target teams distribute parallel do + do i = 1, N + a = 3.14 + !$omp cancellation point do + end do + !$omp end target teams distribute parallel do + + !$omp target parallel do + do i = 1, N + a = 3.14 + !$omp cancellation point do + end do + !$omp end target parallel do + + !$omp parallel + do i = 1, N + a = 3.14 + !ERROR: CANCELLATION POINT DO construct cannot be closely nested inside PARALLEL construct + !$omp cancellation point do + end do + !$omp end parallel + + !$omp parallel + do i = 1, N + a = 3.14 + !$omp cancellation point parallel + end do + !$omp end parallel + + !$omp target parallel + do i = 1, N + a = 3.14 + !$omp cancellation point parallel + end do + !$omp end target parallel + + !$omp target parallel do + do i = 1, N + a = 3.14 + !ERROR: CANCELLATION POINT PARALLEL construct cannot be closely nested inside TARGET PARALLEL DO construct + !$omp cancellation point parallel + end do + !$omp end target parallel do + + !$omp do + do i = 1, N + a = 3.14 + !ERROR: CANCELLATION POINT PARALLEL construct cannot be closely nested inside DO construct + !$omp cancellation point parallel + end do + !$omp end do + +end program main