diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h --- a/flang/lib/Semantics/check-directive-structure.h +++ b/flang/lib/Semantics/check-directive-structure.h @@ -15,7 +15,6 @@ #include "flang/Common/enum-set.h" #include "flang/Semantics/semantics.h" #include "flang/Semantics/tools.h" - #include namespace Fortran::semantics { @@ -43,6 +42,9 @@ template bool Pre(const parser::Statement &statement) { currentStatementSourcePosition_ = statement.source; + if (statement.label.has_value()) { + labels_.insert(*statement.label); + } return true; } @@ -54,6 +56,8 @@ } void Post(const parser::StopStmt &) { EmitBranchOutError("STOP"); } + std::set labels() { return labels_; } + private: parser::MessageFormattedText GetEnclosingMsg() const { return {"Enclosing %s construct"_en_US, upperCaseDirName_}; @@ -103,6 +107,7 @@ parser::CharBlock sourcePosition_; std::string upperCaseDirName_; D currentDirective_; + std::set labels_; }; // Generic structure checker for directives/clauses language such as OpenMP @@ -226,6 +231,9 @@ SayNotMatching(beginDir.source, endDir.source); } } + // Check illegal branching out of `Parser::Block` for `Parser::Name` based + // nodes (examples `Parser::ExitStmt`) along with `Parser::Label` + // based nodes (example `Parser::GotoStmt`). void CheckNoBranching(const parser::Block &block, D directive, const parser::CharBlock &directiveSource); @@ -271,6 +279,11 @@ NoBranchingEnforce noBranchingEnforce{ context_, directiveSource, directive, ContextDirectiveAsFortran()}; parser::Walk(block, noBranchingEnforce); + + LabelEnforce directiveLabelEnforce{context_, noBranchingEnforce.labels(), + directiveSource, + parser::ToUpperCaseLetters(getDirectiveName(directive).str()).c_str()}; + parser::Walk(block, directiveLabelEnforce); } // Check that only clauses included in the given set are present after the given 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 @@ -125,14 +125,7 @@ CheckMatching(beginDir, endDir); PushContextAndClauseSets(beginDir.source, beginDir.v); - - switch (beginDir.v) { - case llvm::omp::OMPD_parallel: - CheckNoBranching(block, llvm::omp::OMPD_parallel, beginDir.source); - break; - default: - break; - } + CheckNoBranching(block, beginDir.v, beginDir.source); } void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) { diff --git a/flang/test/Semantics/omp-parallell01.f90 b/flang/test/Semantics/omp-parallell01.f90 --- a/flang/test/Semantics/omp-parallell01.f90 +++ b/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. @@ -13,7 +12,7 @@ do i = 1, 10 do j = 1, 10 print *, "Hello" - !ERROR: invalid branch to/from OpenMP structured block + !ERROR: Control flow escapes from PARALLEL goto 10 end do end do