[flang-commits] [flang] 5bc6e75 - [Flang][OpenMP] Add semantic checks for invalid branches into or out of OpenMP constructs

via flang-commits flang-commits at lists.llvm.org
Wed Feb 3 02:59:18 PST 2021


Author: Praveen
Date: 2021-02-03T16:09:34+05:30
New Revision: 5bc6e75386e71129d3cbdcae6486a244a5301d54

URL: https://github.com/llvm/llvm-project/commit/5bc6e75386e71129d3cbdcae6486a244a5301d54
DIFF: https://github.com/llvm/llvm-project/commit/5bc6e75386e71129d3cbdcae6486a244a5301d54.diff

LOG: [Flang][OpenMP] Add semantic checks for invalid branches into or out of OpenMP constructs

OpenMP 4.5 - Check invalid branches into OpenMP strucutred blocks.
             Check invalid branches leaving OpenMP structured blocks.

Test cases : omp-do-cycle.f90, omp-invalid-branch.f90

Resolve related test cases marked as XFAIL

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D92735

Added: 
    flang/test/Semantics/omp-do-cycle.f90
    flang/test/Semantics/omp-invalid-branch.f90
    flang/test/Semantics/omp-parallel01.f90
    flang/test/Semantics/omp-parallel02.f90

Modified: 
    flang/lib/Semantics/check-directive-structure.h
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/resolve-directives.cpp
    flang/test/Semantics/omp-clause-validity01.f90
    flang/test/Semantics/omp-do07.f90
    flang/test/Semantics/omp-simd01.f90
    flang/test/Semantics/omp-task01.f90
    flang/test/Semantics/omp-taskloop01.f90
    flang/test/Semantics/omp-taskloop02.f90

Removed: 
    flang/test/Semantics/omp-parallell01.f90
    flang/test/Semantics/omp-parallell02.f90


################################################################################
diff  --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h
index 44b41c14fc221..43495b9cf730b 100644
--- a/flang/lib/Semantics/check-directive-structure.h
+++ b/flang/lib/Semantics/check-directive-structure.h
@@ -42,9 +42,6 @@ template <typename D> class NoBranchingEnforce {
 
   template <typename T> bool Pre(const parser::Statement<T> &statement) {
     currentStatementSourcePosition_ = statement.source;
-    if (statement.label.has_value()) {
-      labels_.insert(*statement.label);
-    }
     return true;
   }
 
@@ -55,8 +52,11 @@ template <typename D> class NoBranchingEnforce {
     }
   }
   void Post(const parser::StopStmt &) { EmitBranchOutError("STOP"); }
-
-  std::set<parser::Label> labels() { return labels_; }
+  void Post(const parser::CycleStmt &cycleStmt) {
+    if (const auto &cycleName{cycleStmt.v}) {
+      CheckConstructNameBranching("CYCLE", cycleName.value());
+    }
+  }
 
 private:
   parser::MessageFormattedText GetEnclosingMsg() const {
@@ -107,7 +107,6 @@ template <typename D> class NoBranchingEnforce {
   parser::CharBlock sourcePosition_;
   std::string upperCaseDirName_;
   D currentDirective_;
-  std::set<parser::Label> labels_;
 };
 
 // Generic structure checker for directives/clauses language such as OpenMP
@@ -236,8 +235,7 @@ class DirectiveStructureChecker : public virtual BaseChecker {
     }
   }
   // Check illegal branching out of `Parser::Block` for `Parser::Name` based
-  // nodes (examples `Parser::ExitStmt`) along with `Parser::Label`
-  // based nodes (example `Parser::GotoStmt`).
+  // nodes (example `Parser::ExitStmt`)
   void CheckNoBranching(const parser::Block &block, D directive,
       const parser::CharBlock &directiveSource);
 
@@ -283,11 +281,6 @@ void DirectiveStructureChecker<D, C, PC, ClauseEnumSize>::CheckNoBranching(
   NoBranchingEnforce<D> noBranchingEnforce{
       context_, directiveSource, directive, ContextDirectiveAsFortran()};
   parser::Walk(block, noBranchingEnforce);
-
-  auto construct{parser::ToUpperCaseLetters(getDirectiveName(directive).str())};
-  LabelEnforce directiveLabelEnforce{context_, noBranchingEnforce.labels(),
-      directiveSource, construct.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
index 2803f2f28a4cb..bb642dc0e92c2 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -141,6 +141,12 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
     PushContextAndClauseSets(beginDir.source, llvm::omp::Directive::OMPD_do);
   }
   SetLoopInfo(x);
+
+  if (const auto &doConstruct{
+          std::get<std::optional<parser::DoConstruct>>(x.t)}) {
+    const auto &doBlock{std::get<parser::Block>(doConstruct->t)};
+    CheckNoBranching(doBlock, beginDir.v, beginDir.source);
+  }
 }
 const parser::Name OmpStructureChecker::GetLoopIndex(
     const parser::DoConstruct *x) {
@@ -221,6 +227,10 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
   CheckMatching<parser::OmpSectionsDirective>(beginDir, endDir);
 
   PushContextAndClauseSets(beginDir.source, beginDir.v);
+  const auto &sectionBlocks{std::get<parser::OmpSectionBlocks>(x.t)};
+  for (const auto &block : sectionBlocks.v) {
+    CheckNoBranching(block, beginDir.v, beginDir.source);
+  }
 }
 
 void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
@@ -324,6 +334,8 @@ void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) {
 void OmpStructureChecker::Enter(const parser::OpenMPCriticalConstruct &x) {
   const auto &dir{std::get<parser::OmpCriticalDirective>(x.t)};
   PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_critical);
+  const auto &block{std::get<parser::Block>(x.t)};
+  CheckNoBranching(block, llvm::omp::Directive::OMPD_critical, dir.source);
 }
 
 void OmpStructureChecker::Leave(const parser::OpenMPCriticalConstruct &) {

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 81e0ee61df4a9..a73357132e59e 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -48,6 +48,11 @@ template <typename T> class DirectiveAttributeVisitor {
     CHECK(!dirContext_.empty());
     return dirContext_.back();
   }
+  std::optional<DirContext> GetContextIf() {
+    return dirContext_.empty()
+        ? std::nullopt
+        : std::make_optional<DirContext>(dirContext_.back());
+  }
   void PushContext(const parser::CharBlock &source, T dir) {
     dirContext_.emplace_back(source, dir, context_.FindScope(source));
   }
@@ -229,6 +234,41 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   template <typename A> bool Pre(const A &) { return true; }
   template <typename A> void Post(const A &) {}
 
+  template <typename A> bool Pre(const parser::Statement<A> &statement) {
+    currentStatementSource_ = statement.source;
+    // Keep track of the labels in all the labelled statements
+    if (statement.label) {
+      auto label{statement.label.value()};
+      // Get the context to check if the labelled statement is in an
+      // enclosing OpenMP construct
+      std::optional<DirContext> thisContext{GetContextIf()};
+      targetLabels_.emplace(
+          label, std::make_pair(currentStatementSource_, thisContext));
+      // Check if a statement that causes a jump to the 'label'
+      // has already been encountered
+      auto range{sourceLabels_.equal_range(label)};
+      for (auto it{range.first}; it != range.second; ++it) {
+        // Check if both the statement with 'label' and the statement that
+        // causes a jump to the 'label' are in the same scope
+        CheckLabelContext(it->second.first, currentStatementSource_,
+            it->second.second, thisContext);
+      }
+    }
+    return true;
+  }
+
+  bool Pre(const parser::InternalSubprogram &) {
+    // Clear the labels being tracked in the previous scope
+    ClearLabels();
+    return true;
+  }
+
+  bool Pre(const parser::ModuleSubprogram &) {
+    // Clear the labels being tracked in the previous scope
+    ClearLabels();
+    return true;
+  }
+
   bool Pre(const parser::SpecificationPart &x) {
     Walk(std::get<std::list<parser::OpenMPDeclarativeConstruct>>(x.t));
     return true;
@@ -263,6 +303,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   bool Pre(const parser::OpenMPSectionsConstruct &);
   void Post(const parser::OpenMPSectionsConstruct &) { PopContext(); }
 
+  bool Pre(const parser::OpenMPCriticalConstruct &);
+  void Post(const parser::OpenMPCriticalConstruct &) { PopContext(); }
+
   bool Pre(const parser::OpenMPDeclareSimdConstruct &x) {
     PushContext(x.source, llvm::omp::Directive::OMPD_declare_simd);
     const auto &name{std::get<std::optional<parser::Name>>(x.t)};
@@ -325,6 +368,30 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   }
   void Post(const parser::Name &);
 
+  // Keep track of labels in the statements that causes jumps to target labels
+  void Post(const parser::GotoStmt &gotoStmt) { CheckSourceLabel(gotoStmt.v); }
+  void Post(const parser::ComputedGotoStmt &computedGotoStmt) {
+    for (auto &label : std::get<std::list<parser::Label>>(computedGotoStmt.t)) {
+      CheckSourceLabel(label);
+    }
+  }
+  void Post(const parser::ArithmeticIfStmt &arithmeticIfStmt) {
+    CheckSourceLabel(std::get<1>(arithmeticIfStmt.t));
+    CheckSourceLabel(std::get<2>(arithmeticIfStmt.t));
+    CheckSourceLabel(std::get<3>(arithmeticIfStmt.t));
+  }
+  void Post(const parser::AssignedGotoStmt &assignedGotoStmt) {
+    for (auto &label : std::get<std::list<parser::Label>>(assignedGotoStmt.t)) {
+      CheckSourceLabel(label);
+    }
+  }
+  void Post(const parser::AltReturnSpec &altReturnSpec) {
+    CheckSourceLabel(altReturnSpec.v);
+  }
+  void Post(const parser::ErrLabel &errLabel) { CheckSourceLabel(errLabel.v); }
+  void Post(const parser::EndLabel &endLabel) { CheckSourceLabel(endLabel.v); }
+  void Post(const parser::EorLabel &eorLabel) { CheckSourceLabel(eorLabel.v); }
+
   const parser::OmpClause *associatedClause{nullptr};
   void SetAssociatedClause(const parser::OmpClause &c) {
     associatedClause = &c;
@@ -357,6 +424,13 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   std::vector<const parser::Name *> allocateNames_; // on one directive
   SymbolSet privateDataSharingAttributeObjects_; // on one directive
   SymbolSet stmtFunctionExprSymbols_;
+  std::multimap<const parser::Label,
+      std::pair<parser::CharBlock, std::optional<DirContext>>>
+      sourceLabels_;
+  std::map<const parser::Label,
+      std::pair<parser::CharBlock, std::optional<DirContext>>>
+      targetLabels_;
+  parser::CharBlock currentStatementSource_;
 
   void AddAllocateName(const parser::Name *&object) {
     allocateNames_.push_back(object);
@@ -394,6 +468,13 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause);
   void CheckPrivateDSAObject(
       const parser::Name &, const Symbol &, Symbol::Flag);
+  void CheckSourceLabel(const parser::Label &);
+  void CheckLabelContext(const parser::CharBlock, const parser::CharBlock,
+      std::optional<DirContext>, std::optional<DirContext>);
+  void ClearLabels() {
+    sourceLabels_.clear();
+    targetLabels_.clear();
+  };
 };
 
 template <typename T>
@@ -904,6 +985,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPBlockConstruct &x) {
   case llvm::omp::Directive::OMPD_parallel_workshare:
   case llvm::omp::Directive::OMPD_target_teams:
   case llvm::omp::Directive::OMPD_target_parallel:
+  case llvm::omp::Directive::OMPD_taskgroup:
     PushContext(beginDir.source, beginDir.v);
     break;
   default:
@@ -1139,6 +1221,12 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) {
   return true;
 }
 
+bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
+  const auto &criticalDir{std::get<parser::OmpCriticalDirective>(x.t)};
+  PushContext(criticalDir.source, llvm::omp::Directive::OMPD_critical);
+  return true;
+}
+
 bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) {
   PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate);
   const auto &list{std::get<parser::OmpObjectList>(x.t)};
@@ -1434,4 +1522,52 @@ void OmpAttributeVisitor::CheckPrivateDSAObject(
   }
 }
 
+void OmpAttributeVisitor::CheckSourceLabel(const parser::Label &label) {
+  // Get the context to check if the statement causing a jump to the 'label' is
+  // in an enclosing OpenMP construct
+  std::optional<DirContext> thisContext{GetContextIf()};
+  sourceLabels_.emplace(
+      label, std::make_pair(currentStatementSource_, thisContext));
+  // Check if the statement with 'label' to which a jump is being introduced
+  // has already been encountered
+  auto it{targetLabels_.find(label)};
+  if (it != targetLabels_.end()) {
+    // Check if both the statement with 'label' and the statement that causes a
+    // jump to the 'label' are in the same scope
+    CheckLabelContext(currentStatementSource_, it->second.first, thisContext,
+        it->second.second);
+  }
+}
+
+// Check for invalid branch into or out of OpenMP structured blocks
+void OmpAttributeVisitor::CheckLabelContext(const parser::CharBlock source,
+    const parser::CharBlock target, std::optional<DirContext> sourceContext,
+    std::optional<DirContext> targetContext) {
+  if (targetContext &&
+      (!sourceContext ||
+          (sourceContext->scope != targetContext->scope &&
+              !DoesScopeContain(
+                  &targetContext->scope, sourceContext->scope)))) {
+    context_
+        .Say(source, "invalid branch into an OpenMP structured block"_err_en_US)
+        .Attach(target, "In the enclosing %s directive branched into"_en_US,
+            parser::ToUpperCaseLetters(
+                llvm::omp::getOpenMPDirectiveName(targetContext->directive)
+                    .str()));
+  }
+  if (sourceContext &&
+      (!targetContext ||
+          (sourceContext->scope != targetContext->scope &&
+              !DoesScopeContain(
+                  &sourceContext->scope, targetContext->scope)))) {
+    context_
+        .Say(source,
+            "invalid branch leaving an OpenMP structured block"_err_en_US)
+        .Attach(target, "Outside the enclosing %s directive"_en_US,
+            parser::ToUpperCaseLetters(
+                llvm::omp::getOpenMPDirectiveName(sourceContext->directive)
+                    .str()));
+  }
+}
+
 } // namespace Fortran::semantics

diff  --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90
index 1d689ea916996..2a16fe375cc3a 100644
--- a/flang/test/Semantics/omp-clause-validity01.f90
+++ b/flang/test/Semantics/omp-clause-validity01.f90
@@ -172,6 +172,7 @@
       exit
       exit outer
       !ERROR: EXIT to construct 'outofparallel' outside of PARALLEL construct is not allowed
+      !ERROR: EXIT to construct 'outofparallel' outside of DO construct is not allowed
       exit outofparallel
     end do inner
   end do outer

diff  --git a/flang/test/Semantics/omp-do-cycle.f90 b/flang/test/Semantics/omp-do-cycle.f90
new file mode 100644
index 0000000000000..a19835f74afa3
--- /dev/null
+++ b/flang/test/Semantics/omp-do-cycle.f90
@@ -0,0 +1,44 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! Check for cycle statements leaving an OpenMP structured block
+
+program omp_do
+  integer i, j, k
+
+  !$omp parallel
+  foo: do i = 0, 10
+    !$omp do
+    bar: do j = 0, 10
+           !ERROR: CYCLE to construct 'foo' outside of DO construct is not allowed
+           cycle foo
+         end do bar
+    !$omp end do
+  end do foo
+  !$omp end parallel
+
+  foo1: do i = 0, 10
+    !$omp parallel
+    foo2: do k = 0, 10
+      !$omp do
+      foo3: do j = 0, 10
+             !ERROR: CYCLE to construct 'foo1' outside of PARALLEL construct is not allowed
+             !ERROR: CYCLE to construct 'foo1' outside of DO construct is not allowed
+             cycle foo1
+           end do foo3
+      !$omp end do
+      end do foo2
+    !$omp end parallel
+    end do foo1
+
+  bar1: do i = 0, 10
+    !$omp parallel
+    bar2: do k = 0, 10
+      bar3: do j = 0, 10
+             !ERROR: CYCLE to construct 'bar1' outside of PARALLEL construct is not allowed
+             cycle bar1
+           end do bar3
+      end do bar2
+    !$omp end parallel
+    end do bar1
+
+end program omp_do

diff  --git a/flang/test/Semantics/omp-do07.f90 b/flang/test/Semantics/omp-do07.f90
index 670e3cf4e08bf..7b0609df32727 100644
--- a/flang/test/Semantics/omp-do07.f90
+++ b/flang/test/Semantics/omp-do07.f90
@@ -1,6 +1,4 @@
-! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
-! XFAIL:*
-
+! RUN: not %f18 -fparse-only -fopenmp %s 2>&1 | FileCheck %s
 ! OpenMP Version 4.5
 ! 2.7.1 Loop Construct
 ! No statement in the associated loops other than the DO statements
@@ -13,12 +11,13 @@ program omp_do
   do i = 1, 10
     do j = 1, 10
       print *, "Hello"
-      !ERROR: invalid branch to/from OpenMP structured block
+      !CHECK: invalid branch leaving an OpenMP structured block
       goto 10
     end do
   end do
   !$omp end do
 
+  !CHECK: Outside the enclosing DO directive
   10 stop
 
 end program omp_do

diff  --git a/flang/test/Semantics/omp-invalid-branch.f90 b/flang/test/Semantics/omp-invalid-branch.f90
new file mode 100644
index 0000000000000..df1eaf1816310
--- /dev/null
+++ b/flang/test/Semantics/omp-invalid-branch.f90
@@ -0,0 +1,107 @@
+! RUN: not %f18 -fparse-only -fopenmp %s 2>&1 | FileCheck %s
+! OpenMP Version 4.5
+! Check invalid branches into or out of OpenMP structured blocks.
+
+subroutine omp_err_end_eor(a, b, x)
+  integer x
+
+  !$omp parallel
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing PARALLEL directive branched into
+
+  !CHECK: invalid branch leaving an OpenMP structured block
+  !CHECK: Outside the enclosing PARALLEL directive
+  open (10, file="myfile.dat", err=100)
+  !CHECK: invalid branch leaving an OpenMP structured block
+  !CHECK: Outside the enclosing PARALLEL directive
+
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing PARALLEL directive branched into
+
+  !CHECK: invalid branch leaving an OpenMP structured block
+  !CHECK: Outside the enclosing PARALLEL directive
+  read (10, 20, end=200, size=x, advance='no', eor=300) a
+  !$omp end parallel
+
+  goto 99
+  99 close (10)
+  goto 40
+  !$omp parallel
+  100 print *, "error opening"
+  !$omp end parallel
+  101 return
+  200 print *, "end of file"
+  202 return
+
+  !$omp parallel
+  300 print *, "end of record"
+  !$omp end parallel
+
+  303 return
+  20 format (1x,F5.1)
+  30 format (2x,F6.2)
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing PARALLEL directive branched into
+  40 open (11, file="myfile2.dat", err=100)
+  goto 50
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing PARALLEL directive branched into
+  50 write (11, 30, err=100) b
+  close (11)
+end subroutine
+
+subroutine omp_alt_return_spec(n, *, *)
+  if (n .eq. 0) return
+  if (n .eq. 1) return 1
+  return 2
+end subroutine
+
+program omp_invalid_branch
+  integer :: n = 0, a = 3, b
+
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing PARALLEL directive branched into
+
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing PARALLEL directive branched into
+  goto (1, 2, 3) a
+
+  assign 2 to b
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing PARALLEL directive branched into
+  goto b (1, 2)
+
+  !$omp parallel
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing SINGLE directive branched into
+
+  !CHECK: invalid branch leaving an OpenMP structured block
+  !CHECK: Outside the enclosing PARALLEL directive
+  3 if(n) 4, 5, 6
+
+  6 print *, 6
+  2 print *, 2
+
+  !$omp single
+  4 print *, 4
+  !$omp end single
+  !$omp end parallel
+
+  1 print *, 1
+  5 print *, 5
+
+  !$omp parallel
+  !CHECK: invalid branch into an OpenMP structured block
+  !CHECK: In the enclosing SINGLE directive branched into
+
+  !CHECK: invalid branch leaving an OpenMP structured block
+  !CHECK: Outside the enclosing PARALLEL directive
+  call omp_alt_return_spec(n, *8, *9)
+  print *, "Normal Return"
+  !$omp single
+  8 print *, "1st alternate return"
+  !$omp end single
+  !$omp end parallel
+  9 print *, "2nd alternate return"
+
+end program

diff  --git a/flang/test/Semantics/omp-parallell01.f90 b/flang/test/Semantics/omp-parallel01.f90
similarity index 65%
rename from flang/test/Semantics/omp-parallell01.f90
rename to flang/test/Semantics/omp-parallel01.f90
index 1a2cae1830bc7..6e66237e74cd9 100644
--- a/flang/test/Semantics/omp-parallell01.f90
+++ b/flang/test/Semantics/omp-parallel01.f90
@@ -1,5 +1,4 @@
-! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
-
+! RUN: not %f18 -fparse-only -fopenmp %s 2>&1 | FileCheck %s
 ! OpenMP Version 4.5
 ! 2.5 parallel construct.
 ! A program that branches into or out of a parallel region
@@ -12,12 +11,13 @@ program omp_parallel
   do i = 1, 10
     do j = 1, 10
       print *, "Hello"
-      !ERROR: Control flow escapes from PARALLEL
+      !CHECK: invalid branch leaving an OpenMP structured block
       goto 10
     end do
   end do
   !$omp end parallel
 
+  !CHECK: Outside the enclosing PARALLEL directive
   10 stop
 
 end program omp_parallel

diff  --git a/flang/test/Semantics/omp-parallell02.f90 b/flang/test/Semantics/omp-parallel02.f90
similarity index 57%
rename from flang/test/Semantics/omp-parallell02.f90
rename to flang/test/Semantics/omp-parallel02.f90
index 3152d5de07143..06b05e26a85a4 100644
--- a/flang/test/Semantics/omp-parallell02.f90
+++ b/flang/test/Semantics/omp-parallel02.f90
@@ -1,6 +1,4 @@
-! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
-! XFAIL: *
-
+! RUN: not %f18 -fparse-only -fopenmp %s 2>&1 | FileCheck %s
 ! OpenMP Version 4.5
 ! 2.5 parallel construct.
 ! A program that branches into or out of a parallel region
@@ -9,13 +7,15 @@
 program omp_parallel
   integer i, j, k
 
-  !ERROR: invalid entry to OpenMP structured block
+  !CHECK: invalid branch into an OpenMP structured block
   goto 10
 
   !$omp parallel
   do i = 1, 10
     do j = 1, 10
       print *, "Hello"
+      !CHECK: In the enclosing PARALLEL directive branched into
+      !CHECK: STOP statement is not allowed in a PARALLEL construct
       10 stop
     end do
   end do

diff  --git a/flang/test/Semantics/omp-simd01.f90 b/flang/test/Semantics/omp-simd01.f90
index 52e3951bb8bbd..da177be321038 100644
--- a/flang/test/Semantics/omp-simd01.f90
+++ b/flang/test/Semantics/omp-simd01.f90
@@ -1,6 +1,4 @@
-! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
-! XFAIL: *
-
+! RUN: not %f18 -fparse-only -fopenmp %s 2>&1 | FileCheck %s
 ! OpenMP Version 4.5
 ! 2.8.1 simd Construct
 ! A program that branches into or out of a simd region is non-conforming.
@@ -12,12 +10,13 @@ program omp_simd
   do i = 1, 10
     do j = 1, 10
       print *, "omp simd"
-      !ERROR: invalid branch to/from OpenMP structured block
+      !CHECK: invalid branch leaving an OpenMP structured block
       goto 10
     end do
   end do
   !$omp end simd
 
+  !CHECK: Outside the enclosing SIMD directive
   10 stop
 
 end program omp_simd

diff  --git a/flang/test/Semantics/omp-task01.f90 b/flang/test/Semantics/omp-task01.f90
index 790ca15f9f811..7824ae22226bd 100644
--- a/flang/test/Semantics/omp-task01.f90
+++ b/flang/test/Semantics/omp-task01.f90
@@ -1,6 +1,4 @@
-! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
-! XFAIL: *
-
+! RUN: not %f18 -fparse-only -fopenmp %s 2>&1 | FileCheck %s
 ! OpenMP Version 4.5
 ! 2.9.1 task Construct
 ! Invalid entry to OpenMP structured block.
@@ -12,12 +10,14 @@ recursive subroutine traverse ( P )
 
   type(Node) :: P
 
-  !ERROR: invalid entry to OpenMP structured block
+  !CHECK: invalid branch into an OpenMP structured block
   goto 10
 
   if (associated(P%left)) then
     !$omp task
     call traverse(P%left)
+    !CHECK: In the enclosing TASK directive branched into
+    !CHECK: STOP statement is not allowed in a TASK construct
     10 stop
     !$omp end task
   endif

diff  --git a/flang/test/Semantics/omp-taskloop01.f90 b/flang/test/Semantics/omp-taskloop01.f90
index 2b373d416d775..516b856c0c52e 100644
--- a/flang/test/Semantics/omp-taskloop01.f90
+++ b/flang/test/Semantics/omp-taskloop01.f90
@@ -1,9 +1,6 @@
 ! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
-! XFAIL: *
-
 ! OpenMP Version 4.5
 ! 2.9.2 taskloop Construct
-! Assert fail for correct test case.
 
 subroutine parallel_work
   integer i

diff  --git a/flang/test/Semantics/omp-taskloop02.f90 b/flang/test/Semantics/omp-taskloop02.f90
index 147cb2a8e87cb..56a3e4e060fed 100644
--- a/flang/test/Semantics/omp-taskloop02.f90
+++ b/flang/test/Semantics/omp-taskloop02.f90
@@ -1,6 +1,4 @@
-! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
-! XFAIL: *
-
+! RUN: not %f18 -fparse-only -fopenmp %s 2>&1 | FileCheck %s
 ! OpenMP Version 4.5
 ! 2.9.2 taskloop Construct
 ! Invalid entry to OpenMP structured block.
@@ -8,12 +6,13 @@
 program omp_taskloop
   integer i , j
 
-  !ERROR: invalid entry to OpenMP structured block
+  !CHECK: invalid branch into an OpenMP structured block
   goto 10
 
   !$omp taskloop private(j) grainsize(500) nogroup
   do i=1,10000
     do j=1,i
+      !CHECK: In the enclosing TASKLOOP directive branched into
       10 call loop_body(i, j)
     end do
   end do


        


More information about the flang-commits mailing list