[flang-commits] [flang] 087826d - [flang][OpenMP] Do not emit an error for CRITICAL inside DEFAULT(NONE) (#216403)

via flang-commits flang-commits at lists.llvm.org
Fri Sep 4 07:11:34 PDT 2026


Author: Leandro Lupori
Date: 2026-09-04T11:11:29-03:00
New Revision: 087826d491eadb8a533f217322ae9d8f6ebba1af

URL: https://github.com/llvm/llvm-project/commit/087826d491eadb8a533f217322ae9d8f6ebba1af
DIFF: https://github.com/llvm/llvm-project/commit/087826d491eadb8a533f217322ae9d8f6ebba1af.diff

LOG: [flang][OpenMP] Do not emit an error for CRITICAL inside DEFAULT(NONE) (#216403)

Fixes #197394
Fixes #197396

Assisted-By: Claude Sonnet 5

Added: 
    flang/test/Semantics/OpenMP/default-none02.f90

Modified: 
    flang/lib/Semantics/resolve-directives.cpp
    flang/test/Semantics/OpenMP/default-none.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 4e3f14e6aa58f..d8414ad0d37bb 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -591,6 +591,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   bool Pre(const parser::OpenMPInvalidDirective &x) { return false; }
 
   bool Pre(const parser::DoConstruct &);
+  bool Pre(const parser::InputImpliedDo &);
+  bool Pre(const parser::OutputImpliedDo &);
 
   bool Pre(const parser::OpenMPSectionsConstruct &);
   void Post(const parser::OpenMPSectionsConstruct &) { PopContext(); }
@@ -2216,6 +2218,28 @@ bool OmpAttributeVisitor::Pre(const parser::DoConstruct &x) {
   return true;
 }
 
+static const parser::Name &GetIoImpliedDoIndex(
+    const parser::IoImpliedDoControl &control) {
+  return parser::UnwrapRef<parser::Name>(control.Name());
+}
+
+// [OMP-5.2] 5.1.1 - Implied-DO indices are predetermined private.
+bool OmpAttributeVisitor::Pre(const parser::InputImpliedDo &x) {
+  if (WithinConstruct()) {
+    ResolveSeqLoopIndexInParallelOrTaskConstruct(
+        GetIoImpliedDoIndex(std::get<parser::IoImpliedDoControl>(x.t)));
+  }
+  return true;
+}
+
+bool OmpAttributeVisitor::Pre(const parser::OutputImpliedDo &x) {
+  if (WithinConstruct()) {
+    ResolveSeqLoopIndexInParallelOrTaskConstruct(
+        GetIoImpliedDoIndex(std::get<parser::IoImpliedDoControl>(x.t)));
+  }
+  return true;
+}
+
 // 2.15.1.1 Data-sharing Attribute Rules - Predetermined
 //   - The loop iteration variable(s) in the associated do-loop(s) of a do,
 //     parallel do, taskloop, or distribute construct is (are) private.
@@ -2731,6 +2755,7 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
         dirContext.defaultDSA == Symbol::Flag::OmpNone) {
       checkDefaultNone = true;
     }
+    bool hasDefaultNoneError{false};
     if (checkDefaultNone) {
       auto defaultNoneError = [&](parser::CharBlock loc, const Symbol *sym) {
         if (crayPtr) {
@@ -2742,13 +2767,30 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
               "The DEFAULT(NONE) clause requires that '%s' must be listed in a data-sharing attribute clause"_err_en_US,
               sym->name());
         }
+        hasDefaultNoneError = true;
       };
+      Symbol *curSymbol{nullptr};
+      if (auto it{scope.find(symbol->name())}; it != scope.end()) {
+        curSymbol = &*it->second;
+      }
+      // Setting the DSA of a symbol with OmpNone DSA in the enclosing construct
+      // is allowed when:
+      // - The DSA is private (no read or write to the original variable).
+      // - The DSA is predetermined (should only private be allowed?).
+      // - The DSA is implicit. The standard seems to allow this only for
+      //   variables that are not referenced in the construct
+      //   (OpenMP 6.0 - 7.5.1 default Clause), but current implementation
+      //   allows the DSA to be implicitly set by a non-leaf directive.
       if (dsa.test(Symbol::Flag::OmpPrivate) ||
           crayPtrDSA.test(Symbol::Flag::OmpPrivate)) {
         checkDefaultNone = false;
-      } else if (dsa.any() || crayPtrDSA.any()) {
+      } else if ((dsa.any() && curSymbol &&
+                     curSymbol->test(Symbol::Flag::OmpExplicit)) ||
+          (crayPtrDSA.any() && crayPtr &&
+              crayPtr->test(Symbol::Flag::OmpExplicit))) {
         defaultNoneError(dirContext.directiveSource, symbol);
-      } else if (dirDepth == (int)dirContext_.size() - 1) {
+      } else if (dsa.none() && crayPtrDSA.none() &&
+          dirDepth == (int)dirContext_.size() - 1) {
         defaultNoneError(name.source, symbol);
       }
     }
@@ -2785,14 +2827,18 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
 
     if (dirContext.defaultDSA == Symbol::Flag::OmpPrivate ||
         dirContext.defaultDSA == Symbol::Flag::OmpFirstPrivate ||
-        dirContext.defaultDSA == Symbol::Flag::OmpShared) {
+        dirContext.defaultDSA == Symbol::Flag::OmpShared ||
+        (dirContext.defaultDSA == Symbol::Flag::OmpNone &&
+            !hasDefaultNoneError)) {
       // 1) default
       // Allowed only with parallel, teams and task generating constructs.
       if (!parallelDir && !taskGenDir && !teamsDir) {
         return;
       }
       dsa = {dirContext.defaultDSA};
-      makeSymbol(dsa);
+      if (dirContext.defaultDSA != Symbol::Flag::OmpNone) {
+        makeSymbol(dsa);
+      }
       PRINT_IMPLICIT_RULE("1) default");
     } else if (parallelDir) {
       // 2) parallel -> shared
@@ -2834,6 +2880,12 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
         PRINT_IMPLICIT_RULE("7) taskgen: firstprivate");
       }
     }
+    if (hasDefaultNoneError &&
+        (dsa.none() || dsa == Symbol::Flags{Symbol::Flag::OmpNone})) {
+      // Set DSA to avoid reporting the same error multiple times.
+      dsa = {Symbol::Flag::OmpShared};
+      makeSymbol(dsa);
+    }
     prevDSA = dsa;
   }
 }

diff  --git a/flang/test/Semantics/OpenMP/default-none.f90 b/flang/test/Semantics/OpenMP/default-none.f90
index a56657ccee467..7ac63928fdba3 100644
--- a/flang/test/Semantics/OpenMP/default-none.f90
+++ b/flang/test/Semantics/OpenMP/default-none.f90
@@ -73,3 +73,48 @@ subroutine internal()
 !$omp end parallel
   end subroutine internal
 end subroutine host_assoc
+
+subroutine parallel_critical()
+  integer :: i
+  !$omp parallel default(none)
+  !$omp critical
+  !$omp parallel
+    do i = 1, 10
+    end do
+  !$omp end parallel
+  !$omp end critical
+  !$omp end parallel
+end subroutine
+
+subroutine implicit_predetermined()
+  !$omp parallel default(none)
+  !$omp parallel
+  !$omp do
+    do i = 0, 10
+    end do
+  !$omp end parallel
+  !$omp end parallel
+end subroutine
+
+subroutine implicit_explicit()
+  !$omp task default(none)
+  !$omp task
+  !$omp parallel private(i)
+  i = 1
+  !$omp end parallel
+  !$omp end task
+  !$omp end task
+end subroutine
+
+! Implied-DO variables in I/O lists are private.
+subroutine implied_do_in_io_list()
+  integer :: a(10)
+
+  !$omp parallel default(none)
+    write(6,*) (i,i=1,10)
+  !$omp end parallel
+
+  !$omp parallel default(none) shared(a)
+    read(5,*) (a(i),i=1,10)
+  !$omp end parallel
+end subroutine

diff  --git a/flang/test/Semantics/OpenMP/default-none02.f90 b/flang/test/Semantics/OpenMP/default-none02.f90
new file mode 100644
index 0000000000000..d2d2c876af65c
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/default-none02.f90
@@ -0,0 +1,23 @@
+!RUN: %python %S/../test_errors.py %s %flang -fopenmp
+! Negative tests for default(none)
+
+! Check that the same error is not displayed for every use of a symbol.
+subroutine repeated_error()
+  real :: B
+
+  !$omp parallel default(none)
+    ! ERROR: The DEFAULT(NONE) clause requires that 'b' must be listed in a data-sharing attribute clause
+    B = B + 1.0 + B
+  !$omp end parallel
+
+  !$omp parallel default(none)
+  !$omp critical
+    ! ERROR: The DEFAULT(NONE) clause requires that 'b' must be listed in a data-sharing attribute clause
+    B = B + 2.0 + B
+    !$omp parallel default(none)
+      ! ERROR: The DEFAULT(NONE) clause requires that 'b' must be listed in a data-sharing attribute clause
+      B = B + 3.0 + B
+    !$omp end parallel
+  !$omp end critical
+  !$omp end parallel
+end subroutine


        


More information about the flang-commits mailing list