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 @@ -97,7 +97,7 @@ dataSharingAttributeObjects_.clear(); } bool HasDataSharingAttributeObject(const Symbol &); - const parser::Name &GetLoopIndex(const parser::DoConstruct &); + const parser::Name *GetLoopIndex(const parser::DoConstruct &); const parser::DoConstruct *GetDoConstructIf( const parser::ExecutionPartConstruct &); Symbol *DeclarePrivateAccessEntity( @@ -560,10 +560,19 @@ } template -const parser::Name &DirectiveAttributeVisitor::GetLoopIndex( +const parser::Name *DirectiveAttributeVisitor::GetLoopIndex( const parser::DoConstruct &x) { using Bounds = parser::LoopControl::Bounds; - return std::get(x.GetLoopControl()->u).name.thing; + if (x.GetLoopControl()) { + return &std::get(x.GetLoopControl()->u).name.thing; + } else { + context_ + .Say(std::get>(x.t).source, + "Loop control is not present in the DO LOOP"_err_en_US) + .Attach(GetContext().directiveSource, + "associated with the enclosing LOOP construct"_en_US); + return nullptr; + } } template @@ -893,11 +902,13 @@ const auto &outer{std::get>(x.t)}; for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) { // go through all the nested do-loops and resolve index variables - const parser::Name &iv{GetLoopIndex(*loop)}; - if (auto *symbol{ResolveAcc(iv, ivDSA, currScope())}) { - symbol->set(Symbol::Flag::AccPreDetermined); - iv.symbol = symbol; // adjust the symbol within region - AddToContextObjectWithDSA(*symbol, ivDSA); + const parser::Name *iv{GetLoopIndex(*loop)}; + if (iv) { + if (auto *symbol{ResolveAcc(*iv, ivDSA, currScope())}) { + symbol->set(Symbol::Flag::AccPreDetermined); + iv->symbol = symbol; // adjust the symbol within region + AddToContextObjectWithDSA(*symbol, ivDSA); + } } const auto &block{std::get(loop->t)}; @@ -1278,20 +1289,21 @@ // TODO:[OpenMP 5.1] DO CONCURRENT indices are private if (x.IsDoNormal()) { if (!dirContext_.empty() && GetContext().withinConstruct) { - if (const auto &iv{GetLoopIndex(x)}; iv.symbol) { - if (!iv.symbol->test(Symbol::Flag::OmpPreDetermined)) { - ResolveSeqLoopIndexInParallelOrTaskConstruct(iv); + const parser::Name *iv{GetLoopIndex(x)}; + if (iv && iv->symbol) { + if (!iv->symbol->test(Symbol::Flag::OmpPreDetermined)) { + ResolveSeqLoopIndexInParallelOrTaskConstruct(*iv); } else { // TODO: conflict checks with explicitly determined DSA } ordCollapseLevel--; if (ordCollapseLevel) { - if (const auto *details{iv.symbol->detailsIf()}) { + if (const auto *details{iv->symbol->detailsIf()}) { const Symbol *tpSymbol = &details->symbol(); if (tpSymbol->test(Symbol::Flag::OmpThreadprivate)) { - context_.Say(iv.source, + context_.Say(iv->source, "Loop iteration variable %s is not allowed in THREADPRIVATE."_err_en_US, - iv.ToString()); + iv->ToString()); } } } @@ -1362,16 +1374,18 @@ const auto &outer{std::get>(x.t)}; for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) { // go through all the nested do-loops and resolve index variables - const parser::Name &iv{GetLoopIndex(*loop)}; - if (auto *symbol{ResolveOmp(iv, ivDSA, currScope())}) { - symbol->set(Symbol::Flag::OmpPreDetermined); - iv.symbol = symbol; // adjust the symbol within region - AddToContextObjectWithDSA(*symbol, ivDSA); - } + const parser::Name *iv{GetLoopIndex(*loop)}; + if (iv) { + if (auto *symbol{ResolveOmp(*iv, ivDSA, currScope())}) { + symbol->set(Symbol::Flag::OmpPreDetermined); + iv->symbol = symbol; // adjust the symbol within region + AddToContextObjectWithDSA(*symbol, ivDSA); + } - const auto &block{std::get(loop->t)}; - const auto it{block.begin()}; - loop = it != block.end() ? GetDoConstructIf(*it) : nullptr; + const auto &block{std::get(loop->t)}; + const auto it{block.begin()}; + loop = it != block.end() ? GetDoConstructIf(*it) : nullptr; + } } CheckAssocLoopLevel(level, GetAssociatedClause()); } diff --git a/flang/test/Semantics/OpenACC/acc-loop.f90 b/flang/test/Semantics/OpenACC/acc-loop.f90 --- a/flang/test/Semantics/OpenACC/acc-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-loop.f90 @@ -250,4 +250,11 @@ end do !$acc end parallel + !$acc loop collapse(2) + do i = 1, N + !ERROR: Loop control is not present in the DO LOOP + do + a(i) = 3.14 + end do + end do end program openacc_loop_validity diff --git a/flang/test/Semantics/OpenMP/omp-do-collapse.f90 b/flang/test/Semantics/OpenMP/omp-do-collapse.f90 --- a/flang/test/Semantics/OpenMP/omp-do-collapse.f90 +++ b/flang/test/Semantics/OpenMP/omp-do-collapse.f90 @@ -22,5 +22,12 @@ !$omp end do end do end do + + !$omp parallel do collapse(2) + do i = 1, 3 + !ERROR: Loop control is not present in the DO LOOP + do + end do + end do end program omp_doCollapse diff --git a/flang/test/Semantics/OpenMP/omp-do-collapse1.f90 b/flang/test/Semantics/OpenMP/omp-do-collapse1.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/OpenMP/omp-do-collapse1.f90 @@ -0,0 +1,14 @@ +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols -fopenmp %s 2>&1 | FileCheck %s +! OpenMP Version 4.5 +! 2.7.1 Loop Construct +program omp_doCollapse + integer:: i + !$omp parallel do collapse(2) + do i = 1, 3 + !CHECK: Loop control is not present in the DO LOOP + !CHECK: associated with the enclosing LOOP construct + do + end do + end do +end program omp_doCollapse +