Index: flang/lib/Semantics/check-omp-structure.h =================================================================== --- flang/lib/Semantics/check-omp-structure.h +++ flang/lib/Semantics/check-omp-structure.h @@ -73,6 +73,10 @@ Directive::OMPD_teams_distribute_simd}; static OmpDirectiveSet taskGeneratingSet{ OmpDirectiveSet{Directive::OMPD_task} | taskloopSet}; +static OmpDirectiveSet noBranchSet{llvm::omp::Directive::OMPD_parallel, + llvm::omp::Directive::OMPD_single, llvm::omp::Directive::OMPD_simd, + llvm::omp::Directive::OMPD_task, llvm::omp::Directive::OMPD_taskloop, + llvm::omp::Directive::OMPD_teams, llvm::omp::Directive::OMPD_do}; } // namespace omp } // namespace llvm Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -126,12 +126,8 @@ PushContextAndClauseSets(beginDir.source, beginDir.v); - switch (beginDir.v) { - case llvm::omp::OMPD_parallel: - CheckNoBranching(block, llvm::omp::OMPD_parallel, beginDir.source); - break; - default: - break; + if (llvm::omp::noBranchSet.test(beginDir.v)) { + CheckNoBranching(block, beginDir.v, beginDir.source); } } Index: flang/lib/Semantics/resolve-directives.cpp =================================================================== --- flang/lib/Semantics/resolve-directives.cpp +++ flang/lib/Semantics/resolve-directives.cpp @@ -225,6 +225,54 @@ template bool Pre(const A &) { return true; } template void Post(const A &) {} + template bool Pre(const parser::Statement &statement) { + currentStatementSource_ = statement.source; + if (statement.label) { + auto label{statement.label.value()}; + DirContext *thisContext{nullptr}; + if (!dirContext_.empty()) { + thisContext = &GetContext(); + } + targetLabels_.emplace(label, thisContext); + auto range{gotoLabels_.equal_range(label)}; + for (auto it{range.first}; it != range.second; ++it) { + CheckGotoContext(it->second.first, it->second.second, thisContext); + } + } + return true; + } + + bool Pre(const parser::GotoStmt &stmt) { + auto label{stmt.v}; + DirContext *thisContext{nullptr}; + if (!dirContext_.empty()) { + thisContext = &GetContext(); + } + gotoLabels_.emplace( + label, std::make_pair(currentStatementSource_, thisContext)); + auto it{targetLabels_.find(label)}; + if (it != targetLabels_.end()) { + CheckGotoContext(currentStatementSource_, thisContext, it->second); + } + return true; + } + + bool Pre(const parser::ComputedGotoStmt &stmt) { + DirContext *thisContext{nullptr}; + if (!dirContext_.empty()) { + thisContext = &GetContext(); + } + for (auto &label : std::get>(stmt.t)) { + gotoLabels_.emplace( + label, std::make_pair(currentStatementSource_, thisContext)); + auto it{targetLabels_.find(label)}; + if (it != targetLabels_.end()) { + CheckGotoContext(currentStatementSource_, thisContext, it->second); + } + } + return true; + } + bool Pre(const parser::SpecificationPart &x) { Walk(std::get>(x.t)); return true; @@ -340,6 +388,10 @@ std::vector allocateNames_; // on one directive SymbolSet privateDataSharingAttributeObjects_; // on one directive + std::map targetLabels_; + std::multimap> + gotoLabels_; + parser::CharBlock currentStatementSource_; void AddAllocateName(const parser::Name *&object) { allocateNames_.push_back(object); @@ -377,6 +429,7 @@ void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause); void CheckObjectInNamelist( const parser::Name &, const Symbol &, Symbol::Flag); + void CheckGotoContext(const parser::CharBlock, DirContext *, DirContext *); }; template @@ -1278,4 +1331,17 @@ } } +void OmpAttributeVisitor::CheckGotoContext(const parser::CharBlock source, + DirContext *gotoContext, DirContext *labelContext) { + if (labelContext && !gotoContext && + llvm::omp::noBranchSet.test(labelContext->directive)) { + context_.Say(source, "invalid entry to OpenMP structured block"_err_en_US); + } else if (gotoContext && + (!labelContext || gotoContext->scope != labelContext->scope) && + llvm::omp::noBranchSet.test(gotoContext->directive)) { + context_.Say( + source, "invalid branch to/from OpenMP structured block"_err_en_US); + } +} + } // namespace Fortran::semantics Index: flang/test/Semantics/omp-do07.f90 =================================================================== --- flang/test/Semantics/omp-do07.f90 +++ flang/test/Semantics/omp-do07.f90 @@ -1,5 +1,4 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL:* ! OpenMP Version 4.5 ! 2.7.1 Loop Construct Index: flang/test/Semantics/omp-parallell01.f90 =================================================================== --- flang/test/Semantics/omp-parallell01.f90 +++ flang/test/Semantics/omp-parallell01.f90 @@ -1,5 +1,4 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * ! OpenMP Version 4.5 ! 2.5 parallel construct. Index: flang/test/Semantics/omp-parallell02.f90 =================================================================== --- flang/test/Semantics/omp-parallell02.f90 +++ flang/test/Semantics/omp-parallell02.f90 @@ -1,5 +1,4 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * ! OpenMP Version 4.5 ! 2.5 parallel construct. @@ -16,6 +15,7 @@ do i = 1, 10 do j = 1, 10 print *, "Hello" + !ERROR: STOP statement is not allowed in a PARALLEL construct 10 stop end do end do Index: flang/test/Semantics/omp-simd01.f90 =================================================================== --- flang/test/Semantics/omp-simd01.f90 +++ flang/test/Semantics/omp-simd01.f90 @@ -1,5 +1,4 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * ! OpenMP Version 4.5 ! 2.8.1 simd Construct Index: flang/test/Semantics/omp-task01.f90 =================================================================== --- flang/test/Semantics/omp-task01.f90 +++ flang/test/Semantics/omp-task01.f90 @@ -1,5 +1,4 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * ! OpenMP Version 4.5 ! 2.9.1 task Construct @@ -18,6 +17,7 @@ if (associated(P%left)) then !$omp task call traverse(P%left) + !ERROR: STOP statement is not allowed in a TASK construct 10 stop !$omp end task endif Index: flang/test/Semantics/omp-taskloop02.f90 =================================================================== --- flang/test/Semantics/omp-taskloop02.f90 +++ flang/test/Semantics/omp-taskloop02.f90 @@ -1,5 +1,4 @@ ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp -! XFAIL: * ! OpenMP Version 4.5 ! 2.9.2 taskloop Construct