[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