[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