diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index bbb105e3516da..45329b5cca9c0 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -1183,13 +1183,23 @@ void AccAttributeVisitor::CheckAssociatedLoopIndex( } const auto getNextDoConstruct = - [this](const parser::Block &block) -> const parser::DoConstruct * { + [this](const parser::Block &block, + std::int64_t &level) -> const parser::DoConstruct * { for (const auto &entry : block) { if (const auto *doConstruct = GetDoConstructIf(entry)) { return doConstruct; } else if (parser::Unwrap(entry)) { // It is allowed to have a compiler directive associated with the loop. continue; + } else if (const auto &accLoop{ + parser::Unwrap(entry)}) { + if (level == 0) + break; + const auto &beginDir{ + std::get(accLoop->t)}; + context_.Say(beginDir.source, + "LOOP directive not expected in COLLAPSE loop nest"_err_en_US); + level = 0; } else { break; } @@ -1198,11 +1208,12 @@ void AccAttributeVisitor::CheckAssociatedLoopIndex( }; const auto &outer{std::get>(x.t)}; - for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) { + for (const parser::DoConstruct *loop{&*outer}; loop && level > 0;) { // Go through all nested loops to ensure index variable exists. GetLoopIndex(*loop); const auto &block{std::get(loop->t)}; - loop = getNextDoConstruct(block); + --level; + loop = getNextDoConstruct(block, level); } CHECK(level == 0); } diff --git a/flang/test/Semantics/OpenACC/acc-loop.f90 b/flang/test/Semantics/OpenACC/acc-loop.f90 index 1c0a515441f43..ee1e6e0cce097 100644 --- a/flang/test/Semantics/OpenACC/acc-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-loop.f90 @@ -268,4 +268,12 @@ program openacc_loop_validity end do !$acc end loop + !$acc loop collapse(2) + do i = 1, 10 + !ERROR: LOOP directive not expected in COLLAPSE loop nest + !$acc loop + do j = 1, 10 + end do + end do + end program openacc_loop_validity