[flang-commits] [flang] [Flang][OpenMP] DEFAULT(NONE) error checking on implicit references (PR #182214)

Phoebe Linck via flang-commits flang-commits at lists.llvm.org
Tue Mar 3 12:05:02 PST 2026


https://github.com/phi-bee updated https://github.com/llvm/llvm-project/pull/182214

>From e89f49b0b8242e09050b3356e67955c5aa632db8 Mon Sep 17 00:00:00 2001
From: Phoebe Linck <phoebe.linck at hpe.com>
Date: Tue, 17 Feb 2026 21:42:29 -0600
Subject: [PATCH] [Flang][OpenMP] DEFAULT(NONE) error checking on implicit
 references

---
 flang/lib/Semantics/resolve-directives.cpp | 55 +++++++++++++---------
 flang/test/Semantics/OpenMP/resolve05.f90  | 25 ++++++++++
 2 files changed, 58 insertions(+), 22 deletions(-)

diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 22f66aafea941..e3a14a795cbe3 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1142,7 +1142,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   void IssueNonConformanceWarning(llvm::omp::Directive D,
       parser::CharBlock source, unsigned EmitFromVersion);
 
-  void CreateImplicitSymbols(const Symbol *symbol);
+  void CreateImplicitSymbols(const parser::Name &, const Symbol *symbol);
 
   void AddToContextObjectWithExplicitDSA(Symbol &symbol, Symbol::Flag flag) {
     AddToContextObjectWithDSA(symbol, flag);
@@ -2696,7 +2696,8 @@ static bool IsTargetCaptureImplicitlyFirstprivatizeable(const Symbol &symbol,
       symbol.details());
 }
 
-void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) {
+void OmpAttributeVisitor::CreateImplicitSymbols(
+    const parser::Name &name, const Symbol *symbol) {
   if (!IsPrivatizable(symbol)) {
     return;
   }
@@ -2707,6 +2708,7 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) {
   // OMP 5.2 5.1.1 - Variables Referenced in a Construct
   Symbol *lastDeclSymbol = nullptr;
   Symbol::Flags prevDSA;
+  bool checkDefaultNone = false;
   for (int dirDepth{0}; dirDepth < (int)dirContext_.size(); ++dirDepth) {
     DirContext &dirContext = dirContext_[dirDepth];
     Symbol::Flags dsa;
@@ -2793,6 +2795,33 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) {
     LLVM_DEBUG(llvm::dbgs()
         << "HasStaticStorageDuration(" << symbol->name() << "):\n");
 
+    if ((checkDefaultNone = checkDefaultNone |
+                (dsa.none() &&
+                    dirContext.defaultDSA == Symbol::Flag::OmpNone))) {
+      auto defaultNoneError = [&](parser::CharBlock loc, const Symbol *sym) {
+        if (sym->GetUltimate().test(Symbol::Flag::CrayPointee)) {
+          std::string crayPtrName{
+              semantics::GetCrayPointer(*sym).name().ToString()};
+          if (!IsObjectWithDSA(*currScope().FindSymbol(crayPtrName))) {
+            context_.Say(loc,
+                "The DEFAULT(NONE) clause requires that the Cray Pointer '%s' must be listed in a data-sharing attribute clause"_err_en_US,
+                crayPtrName);
+          }
+        } else {
+          context_.Say(loc,
+              "The DEFAULT(NONE) clause requires that '%s' must be listed in a data-sharing attribute clause"_err_en_US,
+              sym->name());
+        }
+      };
+      if (dsa.test(Symbol::Flag::OmpPrivate)) {
+        checkDefaultNone = false;
+      } else if (dsa.any()) {
+        defaultNoneError(dirContext.directiveSource, symbol);
+      } else if (dirDepth == (int)dirContext_.size() - 1) {
+        defaultNoneError(name.source, symbol);
+      }
+    }
+
     if (dsa.any()) {
       if (parallelDir || taskGenDir || teamsDir) {
         Symbol *prevDeclSymbol{lastDeclSymbol};
@@ -2953,24 +2982,6 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
       if (Symbol * found{currScope().FindSymbol(name.source)}) {
         if (symbol != found) {
           name.symbol = found; // adjust the symbol within region
-        } else if (GetContext().defaultDSA == Symbol::Flag::OmpNone &&
-            !symbol->GetUltimate().test(Symbol::Flag::OmpThreadprivate) &&
-            // Exclude indices of sequential loops that are privatised in
-            // the scope of the parallel region, and not in this scope.
-            // TODO: check whether this should be caught in IsObjectWithDSA
-            !symbol->test(Symbol::Flag::OmpPrivate)) {
-          if (symbol->GetUltimate().test(Symbol::Flag::CrayPointee)) {
-            std::string crayPtrName{
-                semantics::GetCrayPointer(*symbol).name().ToString()};
-            if (!IsObjectWithDSA(*currScope().FindSymbol(crayPtrName)))
-              context_.Say(name.source,
-                  "The DEFAULT(NONE) clause requires that the Cray Pointer '%s' must be listed in a data-sharing attribute clause"_err_en_US,
-                  crayPtrName);
-          } else {
-            context_.Say(name.source,
-                "The DEFAULT(NONE) clause requires that '%s' must be listed in a data-sharing attribute clause"_err_en_US,
-                symbol->name());
-          }
         }
       }
     }
@@ -3024,7 +3035,7 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
     // we don't need to do anything here (i.e. no flags are needed or
     // anything else).
     if (!IsLocalInsideScope(*symbol, currScope())) {
-      CreateImplicitSymbols(symbol);
+      CreateImplicitSymbols(name, symbol);
     }
   } // within OpenMP construct
 }
@@ -3152,7 +3163,7 @@ void OmpAttributeVisitor::ResolveOmpDesignator(
     // constructs properly capture the variable.
     const Symbol *origSymbol{name->symbol};
     if (origSymbol && privateDataSharingAttributeFlags.test(ompFlag)) {
-      CreateImplicitSymbols(origSymbol);
+      CreateImplicitSymbols(*name, origSymbol);
     }
     if (ompFlag == Symbol::Flag::OmpReduction) {
       // Using variables inside of a namelist in OpenMP reductions
diff --git a/flang/test/Semantics/OpenMP/resolve05.f90 b/flang/test/Semantics/OpenMP/resolve05.f90
index c4cebb48ac5c2..d51849df22ca1 100644
--- a/flang/test/Semantics/OpenMP/resolve05.f90
+++ b/flang/test/Semantics/OpenMP/resolve05.f90
@@ -29,8 +29,33 @@ subroutine default_none_seq_loop
   enddo
 end subroutine
 
+! Test that DEFAULT(NONE) error check sees implicit references
+subroutine default_none_nested()
+  integer :: a
+
+  !$omp parallel default(none)
+  !$omp task
+  !ERROR: The DEFAULT(NONE) clause requires that 'a' must be listed in a data-sharing attribute clause
+  a = 1
+  !$omp end task
+  !$omp end parallel
+end subroutine default_none_nested
+
+! Test that we do not error for an explicitly privatized variable
+subroutine default_none_private()
+  integer :: a
+
+  !$omp parallel default(none)
+  !$omp task private(a)
+    a = 1
+  !$omp end task
+  !$omp end parallel
+end subroutine
+
 program mm
   call default_none()
   call default_none_seq_loop()
+  call default_none_nested()
+  call default_none_private()
   !TODO: private, firstprivate, shared
 end



More information about the flang-commits mailing list