diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -187,6 +187,7 @@ void Enter(const parser::OmpLinearClause &); void Enter(const parser::OmpMapClause &); void Enter(const parser::OmpScheduleClause &); + void Enter(const parser::OpenMPThreadprivate &); private: bool HasInvalidWorksharingNesting( @@ -213,6 +214,15 @@ void CheckIsLoopIvPartOfClause( llvmOmpClause clause, const parser::OmpObjectList &ompObjectList); void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock); + + void CheckIvForThreadPrivate(const parser::OpenMPLoopConstruct &x); + void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x); + void CheckDoWhile(const parser::OpenMPLoopConstruct &x); + void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x); + std::int64_t GetCollapseLevel(const parser::OpenMPLoopConstruct &x); + void CheckIfDoOrderedClause(const parser::OmpBlockDirective &blkDirectiv); + + std::vector threadPrivateSymbols; }; } // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_ diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -84,6 +84,49 @@ parser::CharBlock source_; }; +class OmpCycleChecker { +public: + OmpCycleChecker(SemanticsContext &context, std::int64_t cycleLevel) + : context_{context}, cycleLevel_{cycleLevel} {} + + template bool Pre(const T &) { return true; } + template void Post(const T &) {} + + bool Pre(const parser::DoConstruct &dc) { + cycleLevel_--; + const auto &labelName{std::get<0>(std::get<0>(dc.t).statement.t)}; + if (labelName) { + labelNamesandLevels_.emplace(labelName.value().ToString(), cycleLevel_); + } + return true; + } + + bool Pre(const parser::CycleStmt &cyclestmt) { + std::map::iterator it; + bool err{false}; + if (cyclestmt.v) { + it = labelNamesandLevels_.find(cyclestmt.v->source.ToString()); + err = (it != labelNamesandLevels_.end() && it->second > 0) ? true : false; + } + if (cycleLevel_ > 0 || err) { + context_.Say(*cyclesource_, + "CYCLE statement to non-innermost collapsed !$OMP DO loop"_err_en_US); + } + return true; + } + + bool Pre(const parser::Statement &actionstmt) { + cyclesource_ = &actionstmt.source; + return true; + } + +private: + SemanticsContext &context_; + const parser::CharBlock *cyclesource_; + std::int64_t cycleLevel_; + std::map labelNamesandLevels_; +}; + bool OmpStructureChecker::HasInvalidWorksharingNesting( const parser::CharBlock &source, const OmpDirectiveSet &set) { // set contains all the invalid closely nested directives @@ -141,6 +184,10 @@ PushContextAndClauseSets(beginDir.source, llvm::omp::Directive::OMPD_do); } SetLoopInfo(x); + CheckDoWhile(x); + CheckLoopItrVariableIsInt(x); + CheckIvForThreadPrivate(x); + CheckCycleConstraints(x); } const parser::Name OmpStructureChecker::GetLoopIndex( const parser::DoConstruct *x) { @@ -157,6 +204,102 @@ } } } +void OmpStructureChecker::CheckDoWhile(const parser::OpenMPLoopConstruct &x) { + const auto &beginLoopDir{std::get(x.t)}; + const auto &beginDir{std::get(beginLoopDir.t)}; + if (beginDir.v == llvm::omp::Directive::OMPD_do) { + if (const auto &doConstruct{ + std::get>(x.t)}) { + if (doConstruct.value().IsDoWhile()) { + const auto &doStmt{std::get>( + doConstruct.value().t)}; + context_.Say(doStmt.source, + "The do loop cannot be a DO WHILE with do directive."_err_en_US); + } + } + } +} + +void OmpStructureChecker::CheckLoopItrVariableIsInt( + const parser::OpenMPLoopConstruct &x) { + if (const auto &loopConstruct{ + std::get>(x.t)}) { + for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) { + if (loop->IsDoNormal()) { + const parser::Name &itrVal{GetLoopIndex(loop)}; + if (itrVal.symbol) { + const auto *type{itrVal.symbol->GetType()}; + if (!type->IsNumeric(TypeCategory::Integer)) { + context_.Say(itrVal.source, + "The do-loop iteration" + " variable must be of the type integer."_err_en_US, + itrVal.ToString()); + } + } + } + const auto &block{std::get(loop->t)}; + const auto it{block.begin()}; + loop = it != block.end() ? parser::Unwrap(*it) + : nullptr; + } + } +} + +void OmpStructureChecker::CheckIvForThreadPrivate( + const parser::OpenMPLoopConstruct &x) { + std::int64_t collapseLevel{GetCollapseLevel(x)}; + if (!collapseLevel) + collapseLevel++; + if (const auto &loopConstruct{ + std::get>(x.t)}) { + if (!threadPrivateSymbols.empty()) { + for (const parser::DoConstruct *loop{&*loopConstruct}; + loop && collapseLevel; --collapseLevel) { + if (loop->IsDoNormal()) { + const parser::Name &itrVal{GetLoopIndex(loop)}; + for (const auto *tps : threadPrivateSymbols) { + if (itrVal.symbol->name() == tps->name()) { + context_.Say(itrVal.source, + "Loop iteration variable %s is not allowed in THREADPRIVATE."_err_en_US, + itrVal.ToString()); + } + } + } + const auto &block{std::get(loop->t)}; + const auto it{block.begin()}; + loop = it != block.end() ? parser::Unwrap(*it) + : nullptr; + } + } + } +} + +std::int64_t OmpStructureChecker::GetCollapseLevel( + const parser::OpenMPLoopConstruct &x) { + const auto &beginLoopDir{std::get(x.t)}; + const auto &clauseList{std::get(beginLoopDir.t)}; + std::int64_t collapseLevel{0}; + + for (const auto &clause : clauseList.v) { + if (const auto *collapseClause{ + std::get_if(&clause.u)}) { + if (const auto v{GetIntValue(collapseClause->v)}) { + collapseLevel = *v; + break; + } + } + } + return collapseLevel; +} + +void OmpStructureChecker::CheckCycleConstraints( + const parser::OpenMPLoopConstruct &x) { + std::int64_t collapseLevel{GetCollapseLevel(x)}; + if (collapseLevel) { + OmpCycleChecker ompCycleChecker{context_, collapseLevel}; + parser::Walk(x, ompCycleChecker); + } +} void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) { dirContext_.pop_back(); @@ -193,6 +336,7 @@ HasInvalidWorksharingNesting( beginDir.source, {llvm::omp::Directive::OMPD_do}); } + CheckIfDoOrderedClause(beginDir); PushContextAndClauseSets(beginDir.source, beginDir.v); CheckNoBranching(block, beginDir.v, beginDir.source); @@ -207,6 +351,18 @@ } } +void OmpStructureChecker::CheckIfDoOrderedClause( + const parser::OmpBlockDirective &blkDirective) { + if (blkDirective.v == llvm::omp::OMPD_ordered) { + if (!FindClause(llvm::omp::Clause::OMPC_ordered)) { + context_.Say(blkDirective.source, + "The ORDERED clause must be present on the loop" + " construct if any ORDERED region ever binds" + " to a loop region arising from the loop construct."_err_en_US); + } + } +} + void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) { dirContext_.pop_back(); } @@ -242,6 +398,20 @@ } } +void OmpStructureChecker::Enter(const parser::OpenMPThreadprivate &x) { + const auto &dir{std::get(x.t)}; + PushContextAndClauseSets( + dir.source, llvm::omp::Directive::OMPD_threadprivate); + threadPrivateSymbols.clear(); + const auto &list{std::get(x.t)}; + for (const auto &ompObject : list.v) { + if (const auto *name{parser::Unwrap(ompObject)}) { + if (name->symbol) { + threadPrivateSymbols.push_back(name->symbol); + } + } + } +} void OmpStructureChecker::Enter(const parser::OpenMPDeclareSimdConstruct &x) { const auto &dir{std::get(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_declare_simd); @@ -545,7 +715,6 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar( const parser::OmpObjectList &objList) { - for (const auto &ompObject : objList.v) { std::visit( common::visitors{ diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -988,6 +988,15 @@ } ClearDataSharingAttributeObjects(); SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList)); + + if (beginDir.v == llvm::omp::Directive::OMPD_do) { + if (const auto &doConstruct{ + std::get>(x.t)}) { + if (doConstruct.value().IsDoWhile()) { + return true; + } + } + } PrivatizeAssociatedLoopIndexAndCheckLoopLevel(x); return true; } diff --git a/flang/test/Semantics/omp-do04.f90 b/flang/test/Semantics/omp-do04.f90 --- a/flang/test/Semantics/omp-do04.f90 +++ b/flang/test/Semantics/omp-do04.f90 @@ -1,20 +1,31 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * - ! OpenMP Version 4.5 ! 2.7.1 Loop Construct ! The loop iteration variable may not appear in a threadprivate directive. -program omp_do - integer i, j, k - !$omp do firstprivate(i) - !ERROR: !$OMP DO iteration variable i is not allowed in threadprivate +program omp_do + integer, save:: i, j, k,n + !$omp threadprivate(k,j,i) + !$omp do collapse(2) + !ERROR: Loop iteration variable i is not allowed in THREADPRIVATE. do i = 1, 10 + !ERROR: Loop iteration variable j is not allowed in THREADPRIVATE. do j = 1, 10 print *, "Hello" end do end do !$omp end do - end program omp_do + +program omp_do1 + !$omp threadprivate(k,j,i) + !$omp do + !ERROR: Loop iteration variable i is not allowed in THREADPRIVATE. + do i = 1, 10 + do j = 1, 10 + print *, "Hello" + end do + end do + !$omp end do +end program omp_do1 diff --git a/flang/test/Semantics/omp-do06-positivecases.f90 b/flang/test/Semantics/omp-do06-positivecases.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do06-positivecases.f90 @@ -0,0 +1,23 @@ +! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Loop Construct +! The ordered clause must be present on the loop construct if any ordered +! region ever binds to a loop region arising from the loop construct. + +! A positive case +!DEF: /omp_do MainProgram +program omp_do + !DEF: /omp_do/i ObjectEntity INTEGER(4) + !DEF: /omp_do/j ObjectEntity INTEGER(4) + !DEF: /omp_do/k ObjectEntity INTEGER(4) + integer i, j, k + !$omp do ordered + !DEF: /omp_do/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=1,10 + !$omp ordered + !DEF: /my_func EXTERNAL (Subroutine) ProcEntity + call my_func + !$omp end ordered + end do + !$omp end do +end program omp_do diff --git a/flang/test/Semantics/omp-do06.f90 b/flang/test/Semantics/omp-do06.f90 --- a/flang/test/Semantics/omp-do06.f90 +++ b/flang/test/Semantics/omp-do06.f90 @@ -1,6 +1,4 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL:* - ! OpenMP Version 4.5 ! 2.7.1 Loop Construct ! The ordered clause must be present on the loop construct if any ordered @@ -11,11 +9,25 @@ !$omp do do i = 1, 10 - !ERROR: ‘ordered’ region inside a loop region without an ordered clause. + !ERROR: The ORDERED clause must be present on the loop construct if any ORDERED region ever binds to a loop region arising from the loop construct. !$omp ordered call my_func() !$omp end ordered end do !$omp end do + !$omp do ordered private(i) + do i = 1, 10 + !$omp parallel do + do j = 1, 10 + print *,i + !ERROR: The ORDERED clause must be present on the loop construct if any ORDERED region ever binds to a loop region arising from the loop construct. + !$omp ordered + print *,i + !$omp end ordered + end do + !$omp end parallel do + end do + !$omp end do + end program omp_do diff --git a/flang/test/Semantics/omp-do08.f90 b/flang/test/Semantics/omp-do08.f90 --- a/flang/test/Semantics/omp-do08.f90 +++ b/flang/test/Semantics/omp-do08.f90 @@ -1,19 +1,125 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * - ! OpenMP Version 4.5 ! 2.7.1 Loop Construct -program omp_do +program omp integer i, j, k - !$omp do collapse(2) - do i = 1, 10 + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop - if (i .lt. 5) cycle - do j = 1, 10 - print *, "Hello" + if (i .lt. 1) cycle + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 + do j = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if (i .lt. 1) cycle + do k = 0, 10 + print *, i, j, k + end do end do end do !$omp end do -end program omp_do + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(2) + do i = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if (i .lt. 1) cycle + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(2) + foo: do i = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if (i .lt. 1) cycle foo + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do foo + !$omp end do + + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do 60 i=2,200,2 + do j=1,10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if(i==100) cycle + do k=1,10 + print *,i + end do + end do + 60 continue + !$omp end do + + !$omp do collapse(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if (k .lt. 1) cycle foo + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + !$omp do collapse(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if (k .lt. 1) cycle foo1 + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if (k .lt. 1) cycle foo + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + if (k .lt. 1) cycle foo + foo2: do k = 0, 10 + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + +end program omp diff --git a/flang/test/Semantics/omp-do09.f90 b/flang/test/Semantics/omp-do09.f90 --- a/flang/test/Semantics/omp-do09.f90 +++ b/flang/test/Semantics/omp-do09.f90 @@ -1,22 +1,26 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * - ! OpenMP Version 4.5 ! 2.7.1 Loop Construct ! The do-loop cannot be a DO WHILE or a DO loop without loop control. program omp_do - integer i, j, k - i = 0 + integer :: i = 0,k + !$omp do + !ERROR: The do loop cannot be a DO WHILE with do directive. + do while (i <= 10) + print *, "it",i + i = i+1 + end do + !$omp end do !$omp do - !ERROR: !$OMP DO cannot be a DO WHILE or DO without loop control - do while (i .lt. 10) - do j = 1, 10 - print *, "Hello" + !ERROR: The do loop cannot be a DO WHILE with do directive. + do while (i <= 10) + do while (j <= 10) + print *, "it",k + j = j+1 end do - i = i + 1 + i = i+1 end do !$omp end do - end program omp_do diff --git a/flang/test/Semantics/omp-do10.f90 b/flang/test/Semantics/omp-do10.f90 --- a/flang/test/Semantics/omp-do10.f90 +++ b/flang/test/Semantics/omp-do10.f90 @@ -1,18 +1,37 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * - ! OpenMP Version 4.5 ! 2.7.1 Loop Construct ! The do-loop iteration variable must be of type integer. program omp_do real i, j, k - !$omp do - !ERROR: The do-loop iteration variable must be of type integer. + !ERROR: The do-loop iteration variable must be of the type integer. + do i = 1, 10 + !ERROR: The do-loop iteration variable must be of the type integer. + do j = 1, 10 + print *, "it", i, j + end do + end do + !$omp end do + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + !ERROR: The do-loop iteration variable must be of the type integer. + do i = 1, 10 + !ERROR: The do-loop iteration variable must be of the type integer. + do j = 1, 10 + print *, "it", i, j + end do + end do + !$omp end do + + !$omp do collapse(2) + !ERROR: The do-loop iteration variable must be of the type integer. do i = 1, 10 + !ERROR: The do-loop iteration variable must be of the type integer. do j = 1, 10 - print *, "Hello" + print *, "it", i, j end do end do !$omp end do diff --git a/flang/test/Semantics/omp-do11.f90 b/flang/test/Semantics/omp-do11.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do11.f90 @@ -0,0 +1,55 @@ +! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Do Loop Constructs + +!DEF: /omp_do MainProgram +program omp_do + !DEF: /omp_do/i ObjectEntity INTEGER(4) + !DEF: /omp_do/j ObjectEntity INTEGER(4) + !DEF: /omp_do/k ObjectEntity INTEGER(4) + integer i, j, k + !$omp do + !DEF: /omp_do/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=1,10 + !REF: /omp_do/j + do j=1,10 + !REF: /omp_do/Block1/i + !REF: /omp_do/j + print *, "it", i, j + end do + end do + !$omp end do +end program omp_do + +!DEF: /omp_do1 MainProgram +program omp_do1 + !DEF: /omp_do1/i ObjectEntity INTEGER(4) + !DEF: /omp_do1/j ObjectEntity INTEGER(4) + !DEF: /omp_do1/k (OmpThreadprivate) ObjectEntity INTEGER(4) + !DEF: /omp_do1/n (OmpThreadprivate) ObjectEntity INTEGER(4) + integer i, j, k, n + !$omp threadprivate (k,n) + !$omp do + !DEF: /omp_do1/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=1,10 + !REF: /omp_do1/j + do j=1,10 + print *, "Hello" + end do + end do + !$omp end do +end program omp_do1 + +!DEF: /omp_do3 MainProgram +program omp_do3 + !DEF: /omp_do3/i ObjectEntity INTEGER(4) + !DEF: /omp_do3/k ObjectEntity INTEGER(4) + integer :: i = 0, k + !$omp do + !DEF: /omp_do3/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=1,10 + !REF: /omp_do3/Block1/i + print *, "it", i + end do + !$omp end do +end program omp_do3 diff --git a/flang/test/Semantics/omp-do12.f90 b/flang/test/Semantics/omp-do12.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do12.f90 @@ -0,0 +1,96 @@ +! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Do Loop constructs. + +!DEF: /omp_cycle MainProgram +program omp_cycle + !$omp do collapse(1) + !DEF: /omp_cycle/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + !REF: /omp_cycle/Block1/i + if (i<1) cycle + !DEF: /omp_cycle/j (Implicit) ObjectEntity INTEGER(4) + do j=0,10 + !DEF: /omp_cycle/k (Implicit) ObjectEntity INTEGER(4) + do k=0,10 + !REF: /omp_cycle/Block1/i + !REF: /omp_cycle/j + !REF: /omp_cycle/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(1) + !DEF: /omp_cycle/Block2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + !REF: /omp_cycle/j + do j=0,10 + !REF: /omp_cycle/Block2/i + if (i<1) cycle + !REF: /omp_cycle/k + do k=0,10 + !REF: /omp_cycle/Block2/i + !REF: /omp_cycle/j + !REF: /omp_cycle/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(2) + !DEF: /omp_cycle/Block3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + !DEF: /omp_cycle/Block3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do j=0,10 + !REF: /omp_cycle/k + do k=0,10 + !REF: /omp_cycle/Block3/i + if (i<1) cycle + !REF: /omp_cycle/Block3/i + !REF: /omp_cycle/Block3/j + !REF: /omp_cycle/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(3) + !DEF: /omp_cycle/Block4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + !DEF: /omp_cycle/Block4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do j=0,10 + !DEF: /omp_cycle/Block4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do k=0,10 + !REF: /omp_cycle/Block4/i + if (i<1) cycle + !REF: /omp_cycle/Block4/i + !REF: /omp_cycle/Block4/j + !REF: /omp_cycle/Block4/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(3) + !DEF: /omp_cycle/Block5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo:do i=0,10 + !DEF: /omp_cycle/Block5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo1:do j=0,10 + !DEF: /omp_cycle/Block5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo2:do k=0,10 + !REF: /omp_cycle/Block5/i + if (i<1) cycle foo2 + !REF: /omp_cycle/Block5/i + !REF: /omp_cycle/Block5/j + !REF: /omp_cycle/Block5/k + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do +end program omp_cycle diff --git a/flang/test/Semantics/omp-do13.f90 b/flang/test/Semantics/omp-do13.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do13.f90 @@ -0,0 +1,140 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Loop Construct + +program omp + integer i, j, k + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 + do j = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(2) + do i = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(2) + foo: do i = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do foo + !$omp end do + + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do 60 i=1,10 + do j=1,10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + do k=1,10 + print *,i + end do + end do + 60 continue + !$omp end do + + !$omp do collapse(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + !$omp do collapse(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo1 + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + foo2: do k = 0, 10 + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region + !$omp do collapse(1) + foo2: do k = 0, 10 + print *, i, j, k + end do foo2 + !$omp end do + end do foo1 + end do foo + !$omp end do + +end program omp diff --git a/flang/test/Semantics/omp-do14.f90 b/flang/test/Semantics/omp-do14.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do14.f90 @@ -0,0 +1,91 @@ +! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Do Loop constructs. + +!DEF: /omp_cycle MainProgram +program omp_cycle + !$omp do collapse(1) + !DEF: /omp_cycle/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + cycle + !DEF: /omp_cycle/j (Implicit) ObjectEntity INTEGER(4) + do j=0,10 + !DEF: /omp_cycle/k (Implicit) ObjectEntity INTEGER(4) + do k=0,10 + !REF: /omp_cycle/Block1/i + !REF: /omp_cycle/j + !REF: /omp_cycle/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(1) + !DEF: /omp_cycle/Block2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + !REF: /omp_cycle/j + do j=0,10 + cycle + !REF: /omp_cycle/k + do k=0,10 + !REF: /omp_cycle/Block2/i + !REF: /omp_cycle/j + !REF: /omp_cycle/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(2) + !DEF: /omp_cycle/Block3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + !DEF: /omp_cycle/Block3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do j=0,10 + !REF: /omp_cycle/k + do k=0,10 + cycle + !REF: /omp_cycle/Block3/i + !REF: /omp_cycle/Block3/j + !REF: /omp_cycle/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(3) + !DEF: /omp_cycle/Block4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=0,10 + !DEF: /omp_cycle/Block4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do j=0,10 + !DEF: /omp_cycle/Block4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do k=0,10 + cycle + !REF: /omp_cycle/Block4/i + !REF: /omp_cycle/Block4/j + !REF: /omp_cycle/Block4/k + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(3) + !DEF: /omp_cycle/Block5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo:do i=0,10 + !DEF: /omp_cycle/Block5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo1:do j=0,10 + !DEF: /omp_cycle/Block5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo2:do k=0,10 + cycle foo2 + !REF: /omp_cycle/Block5/i + !REF: /omp_cycle/Block5/j + !REF: /omp_cycle/Block5/k + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do +end program omp_cycle diff --git a/flang/test/Semantics/omp-do15.f90 b/flang/test/Semantics/omp-do15.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do15.f90 @@ -0,0 +1,94 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Loop Construct + +program omp + integer i, j, k + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 + if (i .lt. 1) then + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + end if + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 + do j = 0, 10 + if (i .lt. 1) then + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + end if + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + !!ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + if (i .lt. 1) then + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + else if (i .gt. 3) then + cycle foo1 + end if + do k = 0, 10 + print *, i, j, k + end do + end do foo1 + end do foo + !$omp end do + + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + if (i .lt. 1) then + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + else if (i .gt. 3) then + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo1 + end if + foo2: do k = 0, 10 + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + !$omp do collapse(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + if (i .lt. 1) then + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + else if (i .gt. 3) then + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo1 + else + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + end if + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + +end program omp diff --git a/flang/test/Semantics/omp-do16.f90 b/flang/test/Semantics/omp-do16.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do16.f90 @@ -0,0 +1,77 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Loop Construct + +program omp + integer i, j, k + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 + select case (i) + case(1) + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + end select + do j = 0, 10 + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. + !$omp do collapse(3) + do i = 0, 10 + do j = 0, 10 + select case (i) + case(1) + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle + end select + do k = 0, 10 + print *, i, j, k + end do + end do + end do + !$omp end do + + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + select case (i) + case(1) + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + case(5) + cycle foo1 + end select + do k = 0, 10 + print *, i, j, k + end do + end do foo1 + end do foo + !$omp end do + + !$omp do collapse(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + foo2: do k = 0, 10 + select case (i) + case(1) + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo + case(5) + !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop + cycle foo1 + case(7) + cycle foo2 + end select + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + +end program omp diff --git a/flang/test/Semantics/omp-do17.f90 b/flang/test/Semantics/omp-do17.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do17.f90 @@ -0,0 +1,57 @@ +! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Do Loop constructs. + +!DEF: /test MainProgram +program test + !DEF: /test/i ObjectEntity INTEGER(4) + !DEF: /test/j ObjectEntity INTEGER(4) + !DEF: /test/k ObjectEntity INTEGER(4) + integer i, j, k + !$omp do collapse(2) + !DEF: /test/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo: do i=0,10 + !DEF: /test/Block1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo1: do j=0,10 + !REF: /test/k + foo2: do k=0,10 + !REF: /test/Block1/i + select case (i) + case (5) + cycle foo1 + case (7) + cycle foo2 + end select + !REF: /test/Block1/i + !REF: /test/Block1/j + !REF: /test/k + print *, i, j, k + end do foo2 + end do foo1 + end do foo + + !$omp do collapse(2) + !DEF: /test/Block2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo: do i=0,10 + !DEF: /test/Block2/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + foo1: do j=0,10 + !REF: /test/k + foo2: do k=0,10 + !REF: /test/Block2/i + if (i<3) then + cycle foo1 + !REF: /test/Block2/i + else if (i>8) then + cycle foo1 + else + cycle foo2 + end if + !REF: /test/Block2/i + !REF: /test/Block2/j + !REF: /test/k + print *, i, j, k + end do foo2 + end do foo1 + end do foo +!$omp end do +end program test