[flang-commits] [flang] [Flang][OpenMP] Fix nested PARALLEL SECTIONS validation (PR #179419)

via flang-commits flang-commits at lists.llvm.org
Mon Feb 9 07:23:45 PST 2026


https://github.com/blazie2004 updated https://github.com/llvm/llvm-project/pull/179419

>From 81012d8e6f1c763e49ceebc6c103bcc09bcb6b72 Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Tue, 3 Feb 2026 03:22:22 -0600
Subject: [PATCH 1/2] [Flang][OpenMP] Fix nested PARALLEL SECTIONS validation

---
 flang/lib/Semantics/check-omp-loop.cpp      |  2 +-
 flang/lib/Semantics/check-omp-structure.cpp | 30 +++++++++++++++++----
 flang/lib/Semantics/check-omp-structure.h   |  6 +++--
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 20c52ba3417ad..2ba1432afab02 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -460,7 +460,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
 
     // nesting check
     HasInvalidWorksharingNesting(
-        beginName.source, llvm::omp::nestedWorkshareErrSet);
+        beginName.source, llvm::omp::nestedWorkshareErrSet,beginName.v);
   }
   SetLoopInfo(x);
 
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6f08ebecc7ddf..082fc64441b5a 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -633,11 +633,31 @@ void OmpStructureChecker::CheckMultListItems() {
     CheckMultipleOccurrence(listVars, nameList, clause->source, "LINEAR");
   }
 }
+bool OmpStructureChecker::IsCombinedParallelWorksharing(
+    llvm::omp::Directive directive) const {
+  // Combined parallel-worksharing constructs create their own parallel region
+  // They should not be subject to worksharing nesting restrictions
+  switch (directive) {
+    case llvm::omp::OMPD_parallel_for:
+      return true;
+    case llvm::omp::OMPD_parallel_for_simd:
+      return true;
+    case llvm::omp::OMPD_parallel_sections:
+      return true;
+    case llvm::omp::OMPD_parallel_workshare:
+      return true;
+    default:
+      return false;
+  }
+}
 
 bool OmpStructureChecker::HasInvalidWorksharingNesting(
-    const parser::CharBlock &source, const OmpDirectiveSet &set) {
+    const parser::CharBlock &source, const OmpDirectiveSet &set,llvm::omp::Directive directive) {
   // set contains all the invalid closely nested directives
   // for the given directive (`source` here)
+  if (IsCombinedParallelWorksharing(directive)) {
+    return false;  
+  }
   if (IsCloselyNestedRegion(set)) {
     context_.Say(source,
         "A worksharing region may not be closely nested inside a "
@@ -1056,7 +1076,7 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
   case llvm::omp::OMPD_parallel_workshare:
     CheckWorkshareBlockStmts(block, beginSpec.source);
     HasInvalidWorksharingNesting(
-        beginSpec.source, llvm::omp::nestedWorkshareErrSet);
+        beginSpec.source, llvm::omp::nestedWorkshareErrSet,beginSpec.DirId());
     break;
   case llvm::omp::OMPD_workdistribute:
     if (!CurrentDirectiveIsNested()) {
@@ -1074,7 +1094,7 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
     // TODO: This check needs to be extended while implementing nesting of
     // regions checks.
     HasInvalidWorksharingNesting(
-        beginSpec.source, llvm::omp::nestedWorkshareErrSet);
+        beginSpec.source, llvm::omp::nestedWorkshareErrSet,beginSpec.DirId());
     break;
   case llvm::omp::Directive::OMPD_task:
     for (const auto &clause : beginSpec.Clauses().v) {
@@ -1233,8 +1253,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
     CheckNoBranching(
         std::get<parser::Block>(section.t), beginName.v, beginName.source);
   }
-  HasInvalidWorksharingNesting(
-      beginName.source, llvm::omp::nestedWorkshareErrSet);
+    HasInvalidWorksharingNesting(
+        beginName.source, llvm::omp::nestedWorkshareErrSet,beginSpec.DirId());
 }
 
 void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 9b5b0525dd27f..8afbfd6a6aab2 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -192,10 +192,12 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   void CheckMultListItems();
   void CheckStructureComponent(
       const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
-  bool HasInvalidWorksharingNesting(
-      const parser::CharBlock &, const OmpDirectiveSet &);
+   bool HasInvalidWorksharingNesting(
+      const parser::CharBlock &, const OmpDirectiveSet &,
+      llvm::omp::Directive directive);
   bool IsCloselyNestedRegion(const OmpDirectiveSet &set);
   bool IsNestedInDirective(llvm::omp::Directive directive);
+  bool IsCombinedParallelWorksharing(llvm::omp::Directive directive) const;
   bool InTargetRegion();
   void HasInvalidTeamsNesting(
       const llvm::omp::Directive &dir, const parser::CharBlock &source);

>From 1de8e92872cd59ce6fcf718ce1b9b2a095380d4c Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Mon, 9 Feb 2026 03:18:49 -0600
Subject: [PATCH 2/2] Use OMPD_parallel_do directives and group switch cases

---
 flang/lib/Semantics/check-omp-loop.cpp        |  2 +-
 flang/lib/Semantics/check-omp-structure.cpp   | 15 ++---
 flang/lib/Semantics/check-omp-structure.h     |  5 +-
 .../OpenMP/nested_parallel_sections_valid.f90 | 60 +++++++++++++++++++
 flang/test/Semantics/OpenMP/workshare04.f90   |  1 -
 flang/test/Semantics/OpenMP/workshare05.f90   |  2 +-
 6 files changed, 70 insertions(+), 15 deletions(-)
 create mode 100644 flang/test/Semantics/OpenMP/nested_parallel_sections_valid.f90

diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 2ba1432afab02..5f6bbd90929dc 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -460,7 +460,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
 
     // nesting check
     HasInvalidWorksharingNesting(
-        beginName.source, llvm::omp::nestedWorkshareErrSet,beginName.v);
+        beginName.source, llvm::omp::nestedWorkshareErrSet, beginName.v);
   }
   SetLoopInfo(x);
 
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 082fc64441b5a..686498b5635e2 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -638,12 +638,9 @@ bool OmpStructureChecker::IsCombinedParallelWorksharing(
   // Combined parallel-worksharing constructs create their own parallel region
   // They should not be subject to worksharing nesting restrictions
   switch (directive) {
-    case llvm::omp::OMPD_parallel_for:
-      return true;
-    case llvm::omp::OMPD_parallel_for_simd:
-      return true;
+    case llvm::omp::OMPD_parallel_do:
+    case llvm::omp::OMPD_parallel_do_simd:
     case llvm::omp::OMPD_parallel_sections:
-      return true;
     case llvm::omp::OMPD_parallel_workshare:
       return true;
     default:
@@ -656,7 +653,7 @@ bool OmpStructureChecker::HasInvalidWorksharingNesting(
   // set contains all the invalid closely nested directives
   // for the given directive (`source` here)
   if (IsCombinedParallelWorksharing(directive)) {
-    return false;  
+    return false; 
   }
   if (IsCloselyNestedRegion(set)) {
     context_.Say(source,
@@ -1076,7 +1073,7 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
   case llvm::omp::OMPD_parallel_workshare:
     CheckWorkshareBlockStmts(block, beginSpec.source);
     HasInvalidWorksharingNesting(
-        beginSpec.source, llvm::omp::nestedWorkshareErrSet,beginSpec.DirId());
+        beginSpec.source, llvm::omp::nestedWorkshareErrSet, beginSpec.DirId());
     break;
   case llvm::omp::OMPD_workdistribute:
     if (!CurrentDirectiveIsNested()) {
@@ -1094,7 +1091,7 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
     // TODO: This check needs to be extended while implementing nesting of
     // regions checks.
     HasInvalidWorksharingNesting(
-        beginSpec.source, llvm::omp::nestedWorkshareErrSet,beginSpec.DirId());
+        beginSpec.source, llvm::omp::nestedWorkshareErrSet, beginSpec.DirId());
     break;
   case llvm::omp::Directive::OMPD_task:
     for (const auto &clause : beginSpec.Clauses().v) {
@@ -1254,7 +1251,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
         std::get<parser::Block>(section.t), beginName.v, beginName.source);
   }
     HasInvalidWorksharingNesting(
-        beginName.source, llvm::omp::nestedWorkshareErrSet,beginSpec.DirId());
+        beginName.source, llvm::omp::nestedWorkshareErrSet, beginSpec.DirId());
 }
 
 void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 8afbfd6a6aab2..c5c84593b73df 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -192,9 +192,8 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   void CheckMultListItems();
   void CheckStructureComponent(
       const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
-   bool HasInvalidWorksharingNesting(
-      const parser::CharBlock &, const OmpDirectiveSet &,
-      llvm::omp::Directive directive);
+   bool HasInvalidWorksharingNesting(const parser::CharBlock &,
+       const OmpDirectiveSet &, llvm::omp::Directive directive);
   bool IsCloselyNestedRegion(const OmpDirectiveSet &set);
   bool IsNestedInDirective(llvm::omp::Directive directive);
   bool IsCombinedParallelWorksharing(llvm::omp::Directive directive) const;
diff --git a/flang/test/Semantics/OpenMP/nested_parallel_sections_valid.f90 b/flang/test/Semantics/OpenMP/nested_parallel_sections_valid.f90
new file mode 100644
index 0000000000000..0c57fe2b4ef78
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/nested_parallel_sections_valid.f90
@@ -0,0 +1,60 @@
+! RUN: %flang -fopenmp -c %s
+! Regression test for nested PARALLEL SECTIONS
+! This test verifies that combined parallel-worksharing constructs
+! can be properly nested as they create their own implicit parallel regions.
+
+program test_parallel_sections_nesting
+  implicit none
+  integer :: i, j, n
+  real :: a(10), b(10), c(10)
+  
+  n = 10
+  
+  ! Test 1: PARALLEL SECTIONS nesting PARALLEL SECTIONS
+  !$OMP PARALLEL SECTIONS
+    !$OMP SECTION
+      !$OMP PARALLEL SECTIONS
+        !$OMP SECTION
+          do i = 1, n
+            a(i) = real(i)
+          end do
+        !$OMP SECTION
+          do j = 1, n
+            b(j) = real(j * 2)
+          end do
+      !$OMP END PARALLEL SECTIONS
+    !$OMP SECTION
+      !$OMP PARALLEL DO
+        do i = 1, n
+          c(i) = a(i) + b(i)
+        end do
+      !$OMP END PARALLEL DO
+  !$OMP END PARALLEL SECTIONS
+  
+  ! Test 2: PARALLEL SECTIONS inside PARALLEL
+  !$OMP PARALLEL
+    !$OMP PARALLEL SECTIONS
+      !$OMP SECTION
+        do i = 1, n
+          a(i) = a(i) * 2
+        end do
+      !$OMP SECTION
+        do j = 1, n
+          b(j) = b(j) * 2
+        end do
+    !$OMP END PARALLEL SECTIONS
+  !$OMP END PARALLEL
+  
+  ! Test 3: PARALLEL DO inside PARALLEL SECTIONS
+  !$OMP PARALLEL SECTIONS
+    !$OMP SECTION
+      !$OMP PARALLEL DO
+        do i = 1, n
+          c(i) = c(i) + a(i)
+        end do
+      !$OMP END PARALLEL DO
+    !$OMP SECTION
+      c = c + 1.0
+  !$OMP END PARALLEL SECTIONS
+  
+end program test_parallel_sections_nesting
\ No newline at end of file
diff --git a/flang/test/Semantics/OpenMP/workshare04.f90 b/flang/test/Semantics/OpenMP/workshare04.f90
index 0ec635e52d2b7..e5d6334eaf373 100644
--- a/flang/test/Semantics/OpenMP/workshare04.f90
+++ b/flang/test/Semantics/OpenMP/workshare04.f90
@@ -18,7 +18,6 @@ subroutine omp_workshare(aa, bb, cc, dd, ee, ff, n)
   !$omp end parallel
 
   !ERROR: OpenMP constructs enclosed in WORKSHARE construct may consist of ATOMIC, CRITICAL or PARALLEL constructs only
-  !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
   !$omp parallel workshare
   !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
   !$omp single
diff --git a/flang/test/Semantics/OpenMP/workshare05.f90 b/flang/test/Semantics/OpenMP/workshare05.f90
index b57053e092e67..0bee882341342 100644
--- a/flang/test/Semantics/OpenMP/workshare05.f90
+++ b/flang/test/Semantics/OpenMP/workshare05.f90
@@ -40,7 +40,7 @@ program omp_workshare
   !$omp end single
   !$omp end parallel
 
-  !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
+ 
   !$omp parallel sections
   !$omp section
   aa = my_func()



More information about the flang-commits mailing list