From e2e857798c72c5ff2c744fea492ef0b687e5597b Mon Sep 17 00:00:00 2001 From: Kiran Chandramohan Date: Thu, 28 Nov 2024 23:33:01 +0000 Subject: [PATCH] [Flang][OpenMP] Issue an error for loop directive without a loop Fixes #107500 --- flang/lib/Semantics/resolve-directives.cpp | 33 +++++++++++++--------- flang/test/Semantics/OpenMP/do21.f90 | 27 ++++++++++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 flang/test/Semantics/OpenMP/do21.f90 diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 80e238f3476ac..3e01410f0c1ff 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -1888,22 +1888,29 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel( } 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 (iv) { - if (auto *symbol{ResolveOmp(*iv, ivDSA, currScope())}) { - symbol->set(Symbol::Flag::OmpPreDetermined); - iv->symbol = symbol; // adjust the symbol within region - AddToContextObjectWithDSA(*symbol, ivDSA); - } + if (outer.has_value()) { + 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 (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()); + } else { + context_.Say(GetContext().directiveSource, + "A DO loop must follow the %s directive"_err_en_US, + parser::ToUpperCaseLetters( + llvm::omp::getOpenMPDirectiveName(GetContext().directive).str())); } - CheckAssocLoopLevel(level, GetAssociatedClause()); } void OmpAttributeVisitor::CheckAssocLoopLevel( std::int64_t level, const parser::OmpClause *clause) { diff --git a/flang/test/Semantics/OpenMP/do21.f90 b/flang/test/Semantics/OpenMP/do21.f90 new file mode 100644 index 0000000000000..2f5815c10c11a --- /dev/null +++ b/flang/test/Semantics/OpenMP/do21.f90 @@ -0,0 +1,27 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! Check for existence of loop following a DO directive + +subroutine do1 + !ERROR: A DO loop must follow the DO directive + !$omp do +end subroutine + +subroutine do2 + !ERROR: A DO loop must follow the PARALLEL DO directive + !$omp parallel do +end subroutine + +subroutine do3 + !ERROR: A DO loop must follow the SIMD directive + !$omp simd +end subroutine + +subroutine do4 + !ERROR: A DO loop must follow the DO SIMD directive + !$omp do simd +end subroutine + +subroutine do5 + !ERROR: A DO loop must follow the LOOP directive + !$omp loop +end subroutine