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,42 @@ parser::CharBlock source_; }; +class OmpCycleBlockChecker { +public: + OmpCycleBlockChecker(SemanticsContext &context, parser::CharBlock source, + std::int64_t cycleLevel, + std::map labelNamesandLevels) + : context_{context}, source_{source}, cycleLevel_{cycleLevel}, + labelNamesandLevels_{labelNamesandLevels} {} + + template bool Pre(const T &) { return true; } + template void Post(const T &) {} + + bool Pre(const parser::ActionStmt &actionstmt) { + std::map::iterator it; + bool err{false}; + if (const auto *cyclestmt{ + parser::Unwrap(actionstmt.u)}) { + 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(source_, + "CYCLE statement to non-innermost collapsed !$OMP DO loop"_err_en_US); + } + } + return true; + } + +private: + SemanticsContext &context_; + parser::CharBlock source_; + 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 +177,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 +197,131 @@ } } } +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)}; + std::int64_t cycleLevel{collapseLevel - 1}; + std::map labelNamesandLevels; + parser::CharBlock src{"cycle"}; + if (collapseLevel) { + if (const auto &loopConstruct{ + std::get>(x.t)}) { + for (const parser::DoConstruct *loop{&*loopConstruct}; loop; + --cycleLevel) { + const auto &labelName{std::get<0>(std::get<0>(loop->t).statement.t)}; + if (labelName) { + labelNamesandLevels.emplace(labelName.value().ToString(), cycleLevel); + } + const parser::Block &blk{std::get(loop->t)}; + for (auto iit{blk.begin()}; iit != blk.end(); ++iit) { + + if (const auto &ec{ + parser::Unwrap(iit->u)}) { + if (const auto *actionstmt{ + std::get_if>( + &ec->u)}) { + OmpCycleBlockChecker ompCycleBlockChecker{context_, + actionstmt->source, cycleLevel, labelNamesandLevels}; + parser::Walk(*iit, ompCycleBlockChecker); + } + } + } + const parser::Block &block{std::get(loop->t)}; + const auto it{block.begin()}; + loop = it != block.end() ? parser::Unwrap(*it) + : nullptr; + } + } + } +} void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) { dirContext_.pop_back(); @@ -193,6 +358,7 @@ HasInvalidWorksharingNesting( beginDir.source, {llvm::omp::Directive::OMPD_do}); } + CheckIfDoOrderedClause(beginDir); PushContextAndClauseSets(beginDir.source, beginDir.v); CheckNoBranching(block, beginDir.v, beginDir.source); @@ -207,6 +373,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 +420,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 +737,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,125 @@ +! 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 + +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