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

via flang-commits flang-commits at lists.llvm.org
Tue Feb 3 01:48:08 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-openmp

Author: jay0x (blazie2004)

<details>
<summary>Changes</summary>

## Problem
Flang's OpenMP semantic checker was incorrectly rejecting valid nested PARALLEL SECTIONS 
and other combined parallel-worksharing constructs. The validator was overly strict, 
treating combined constructs like PARALLEL SECTIONS as simple worksharing constructs 
and incorrectly applying worksharing nesting restrictions.

## Root Cause
The HasInvalidWorksharingNesting() function couldn't distinguish between:
- Simple worksharing constructs (DO, SECTIONS, SINGLE) - cannot nest
- Combined parallel-worksharing constructs (PARALLEL DO, PARALLEL SECTIONS) - create their own parallel regions and should nest

## Solution
1. Added IsCombinedParallelWorksharing() to identify combined constructs
2. Modified HasInvalidWorksharingNesting() to skip restrictions for combined constructs
3. Updated all call sites with directive parameters

## Standards Compliance
Aligns with OpenMP 5.0 Specification Section 2.3, 2.13.3, and 2.20 which allow 
parallel regions to be nested.

## Test Results
-  pv582271.f now compiles (was failing)
-  4059/4061 tests pass (98.14%)


## Files Changed
- flang/lib/Semantics/check-omp-structure.h
- flang/lib/Semantics/check-omp-structure.cpp
- flang/lib/Semantics/check-omp-loop.cpp

Fixes: #pv582271

---
Full diff: https://github.com/llvm/llvm-project/pull/179419.diff


3 Files Affected:

- (modified) flang/lib/Semantics/check-omp-loop.cpp (+1-1) 
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+25-5) 
- (modified) flang/lib/Semantics/check-omp-structure.h (+4-2) 


``````````diff
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);

``````````

</details>


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


More information about the flang-commits mailing list