[flang-commits] [flang] c2784e1 - [Flang][OpenMP] DEFAULT(NONE) error checking on implicit references (#182214)
via flang-commits
flang-commits at lists.llvm.org
Wed Mar 4 04:33:56 PST 2026
Author: Phoebe Linck
Date: 2026-03-04T09:33:51-03:00
New Revision: c2784e11cc4405cbc64d1928cbcabbbd0759777b
URL: https://github.com/llvm/llvm-project/commit/c2784e11cc4405cbc64d1928cbcabbbd0759777b
DIFF: https://github.com/llvm/llvm-project/commit/c2784e11cc4405cbc64d1928cbcabbbd0759777b.diff
LOG: [Flang][OpenMP] DEFAULT(NONE) error checking on implicit references (#182214)
A variable with an unspecified data-sharing attribute under a
DEFAULT(NONE) clause only emits an error if the variable is explicitly
referenced in the body of the construct with DEFAULT(NONE).
Ex:
```
!$omp parallel default(none)
!$omp task
a = 1
!$omp end task
!$omp end parallel
end
```
gfortran will error with `‘a’ not specified in enclosing ‘parallel’` on
the above. flang doesn't error.
Fix moves the error check to `CreateImplicitSymbols` and checks the
variable for a violation in any of its enclosing contexts.
Added:
Modified:
flang/lib/Semantics/resolve-directives.cpp
flang/test/Semantics/OpenMP/resolve05.f90
Removed:
################################################################################
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