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 @@ -165,6 +165,12 @@ void CheckIsLoopIvPartOfClause( llvmOmpClause clause, const parser::OmpObjectList &ompObjectList); void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock); + + void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x); + void CheckDoWhile(const parser::OpenMPLoopConstruct &x); + void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x); + std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x); + void CheckIfDoOrderedClause(const parser::OmpBlockDirective &blkDirectiv); }; } // 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); + } + if (cycleLevel_ > 0 || err) { + context_.Say(*cycleSource_, + "CYCLE statement to non-innermost associated loop of an OpenMP DO construct"_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 @@ -147,6 +190,9 @@ const auto &doBlock{std::get(doConstruct->t)}; CheckNoBranching(doBlock, beginDir.v, beginDir.source); } + CheckDoWhile(x); + CheckLoopItrVariableIsInt(x); + CheckCycleConstraints(x); } const parser::Name OmpStructureChecker::GetLoopIndex( const parser::DoConstruct *x) { @@ -163,6 +209,85 @@ } } } +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()); + } + } + } + // Get the next DoConstruct if block is not empty. + const auto &block{std::get(loop->t)}; + const auto it{block.begin()}; + loop = it != block.end() ? parser::Unwrap(*it) + : nullptr; + } + } +} + +std::int64_t OmpStructureChecker::GetOrdCollapseLevel( + const parser::OpenMPLoopConstruct &x) { + const auto &beginLoopDir{std::get(x.t)}; + const auto &clauseList{std::get(beginLoopDir.t)}; + std::int64_t orderedCollapseLevel{1}; + std::int64_t orderedLevel{0}; + 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; + } + } + if (const auto *orderedClause{ + std::get_if(&clause.u)}) { + if (const auto v{GetIntValue(orderedClause->v)}) { + orderedLevel = *v; + } + } + } + if (orderedLevel >= collapseLevel) { + orderedCollapseLevel = orderedLevel; + } else { + orderedCollapseLevel = collapseLevel; + } + return orderedCollapseLevel; +} + +void OmpStructureChecker::CheckCycleConstraints( + const parser::OpenMPLoopConstruct &x) { + std::int64_t ordCollapseLevel{GetOrdCollapseLevel(x)}; + OmpCycleChecker ompCycleChecker{context_, ordCollapseLevel}; + parser::Walk(x, ompCycleChecker); +} void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) { dirContext_.pop_back(); @@ -199,6 +324,7 @@ HasInvalidWorksharingNesting( beginDir.source, {llvm::omp::Directive::OMPD_do}); } + CheckIfDoOrderedClause(beginDir); PushContextAndClauseSets(beginDir.source, beginDir.v); CheckNoBranching(block, beginDir.v, beginDir.source); @@ -213,6 +339,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(); } @@ -583,7 +721,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 @@ -1070,6 +1070,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-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 %flang -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,138 @@ ! RUN: %S/test_errors.sh %s %t %flang -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: CYCLE statement to non-innermost collapsed !$OMP DO loop - if (i .lt. 5) cycle - do j = 1, 10 - print *, "Hello" + + !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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + if (k .lt. 1) cycle foo + print *, i, j, k + end do foo2 + end do foo1 + end do foo + !$omp end do + + + !$omp do ordered(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + 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 + + !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) ordered(3) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + 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 %flang -fopenmp -! XFAIL: * - +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp ! 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 %flang -fopenmp -! XFAIL: * - +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct -! The do-loop iteration variable must be of type integer. +! 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,36 @@ +! 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_do2 MainProgram +program omp_do2 + !DEF: /omp_do2/i ObjectEntity INTEGER(4) + !DEF: /omp_do2/k ObjectEntity INTEGER(4) + integer :: i = 0, k + !$omp do + !DEF: /omp_do2/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=1,10 + !REF: /omp_do2/Block1/i + print *, "it", i + end do + !$omp end do +end program omp_do2 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,185 @@ +! 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 ordered(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + 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 + + !$omp parallel + !$omp do collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + cycle foo + !$omp parallel + !$omp do collapse(2) + foo2: do k = 0, 10 + foo3: do l = 0, 10 + print *, i, j, k, l + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + cycle foo2 + end do foo3 + end do foo2 + !$omp end do + !$omp end parallel + end do foo1 + end do foo + !$omp end do + !$omp end parallel + + !$omp parallel + !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 parallel do ordered(3) collapse(2) + foo: do i = 0, 10 + foo1: do j = 0, 10 + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + cycle foo + !$omp parallel + !$omp parallel do collapse(2) + foo2: do k = 0, 10 + foo3: do l = 0, 10 + print *, i, j, k, l + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + cycle foo2 + end do foo3 + end do foo2 + !$omp end parallel do + !$omp end parallel + end do foo1 + end do foo +!$omp end parallel do +!$omp end parallel + +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 ordered(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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + cycle foo + else if (i .gt. 3) then + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + 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 ordered(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 associated loop of an OpenMP DO construct + cycle foo + else if (i .gt. 3) then + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + cycle foo1 + else + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 associated loop of an OpenMP DO construct + 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 ordered(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 associated loop of an OpenMP DO construct + cycle foo + case(5) + !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct + 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