From 3e276d91c1df923acc3eb52f2e998d68d46c9200 Mon Sep 17 00:00:00 2001 From: Andre Kuhlenschmidt Date: Mon, 25 Aug 2025 10:49:13 -0700 Subject: [PATCH 1/2] initial commit --- flang/lib/Semantics/resolve-directives.cpp | 47 +++++++++++++++---- flang/test/Semantics/OpenACC/acc-parallel.f90 | 22 +++++++++ 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 3c59085812989..05efc4f1da910 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -29,7 +29,6 @@ #include "llvm/Support/Debug.h" #include #include -#include template static Fortran::semantics::Scope *GetScope( @@ -61,6 +60,14 @@ template class DirectiveAttributeVisitor { parser::OmpDefaultmapClause::ImplicitBehavior> defaultMap; + std::optional FindSymbolWithDSA(const Symbol &symbol) { + auto it{objectWithDSA.find(&symbol)}; + if (it != objectWithDSA.end()) { + return std::make_optional(it->second); + } + return std::nullopt; + } + bool withinConstruct{false}; std::int64_t associatedLoopLevel{0}; }; @@ -75,10 +82,20 @@ template class DirectiveAttributeVisitor { : std::make_optional(dirContext_.back()); } void PushContext(const parser::CharBlock &source, T dir, Scope &scope) { - dirContext_.emplace_back(source, dir, scope); + if constexpr (std::is_same_v) { + bool wasEmpty{dirContext_.empty()}; + dirContext_.emplace_back(source, dir, scope); + if (!wasEmpty) { + std::size_t lastIndex{dirContext_.size() - 1}; + dirContext_[lastIndex].defaultDSA = + dirContext_[lastIndex - 1].defaultDSA; + } + } else { + dirContext_.emplace_back(source, dir, scope); + } } void PushContext(const parser::CharBlock &source, T dir) { - dirContext_.emplace_back(source, dir, context_.FindScope(source)); + PushContext(source, dir, context_.FindScope(source)); } void PopContext() { dirContext_.pop_back(); } void SetContextDirectiveSource(parser::CharBlock &dir) { @@ -100,9 +117,21 @@ template class DirectiveAttributeVisitor { AddToContextObjectWithDSA(symbol, flag, GetContext()); } bool IsObjectWithDSA(const Symbol &symbol) { - auto it{GetContext().objectWithDSA.find(&symbol)}; - return it != GetContext().objectWithDSA.end(); + return GetContext().FindSymbolWithDSA(symbol).has_value(); + } + bool IsObjectWithVisibleDSA(const Symbol &symbol) { + for (std::size_t i{dirContext_.size()}; i != 0; i--) { + if (dirContext_[i - 1].FindSymbolWithDSA(symbol).has_value()) { + return true; + } + } + return false; } + + bool WithinContstruct() { + return !dirContext_.empty() && GetContext().withinConstruct; + } + void SetContextAssociatedLoopLevel(std::int64_t level) { GetContext().associatedLoopLevel = level; } @@ -1573,10 +1602,10 @@ void AccAttributeVisitor::Post(const parser::AccDefaultClause &x) { // and adjust the symbol for each Name if necessary void AccAttributeVisitor::Post(const parser::Name &name) { auto *symbol{name.symbol}; - if (symbol && !dirContext_.empty() && GetContext().withinConstruct) { + if (symbol && WithinContstruct()) { symbol = &symbol->GetUltimate(); if (!symbol->owner().IsDerivedType() && !symbol->has() && - !symbol->has() && !IsObjectWithDSA(*symbol)) { + !symbol->has() && !IsObjectWithVisibleDSA(*symbol)) { if (Symbol * found{currScope().FindSymbol(name.source)}) { if (symbol != found) { name.symbol = found; // adjust the symbol within region @@ -1959,7 +1988,7 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct( // till OpenMP-5.0 standard. // In above both cases we skip the privatization of iteration variables. bool OmpAttributeVisitor::Pre(const parser::DoConstruct &x) { - if (!dirContext_.empty() && GetContext().withinConstruct) { + if (WithinContstruct()) { llvm::SmallVector ivs; if (x.IsDoNormal()) { const parser::Name *iv{GetLoopIndex(x)}; @@ -2685,7 +2714,7 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) { void OmpAttributeVisitor::Post(const parser::Name &name) { auto *symbol{name.symbol}; - if (symbol && !dirContext_.empty() && GetContext().withinConstruct) { + if (symbol && WithinContstruct()) { if (IsPrivatizable(symbol) && !IsObjectWithDSA(*symbol)) { // TODO: create a separate function to go through the rules for // predetermined, explicitly determined, and implicitly diff --git a/flang/test/Semantics/OpenACC/acc-parallel.f90 b/flang/test/Semantics/OpenACC/acc-parallel.f90 index 635c547f744c8..52e267f6910da 100644 --- a/flang/test/Semantics/OpenACC/acc-parallel.f90 +++ b/flang/test/Semantics/OpenACC/acc-parallel.f90 @@ -200,3 +200,25 @@ program openacc_parallel_validity !$acc end parallel end program openacc_parallel_validity + +subroutine acc_parallel_default_none + integer :: i, l + real :: a(10,10) + l = 10 + !$acc parallel default(none) + !$acc loop + !ERROR: The DEFAULT(NONE) clause requires that 'l' must be listed in a data-mapping clause + do i = 1, l + !ERROR: The DEFAULT(NONE) clause requires that 'a' must be listed in a data-mapping clause + a(1,i) = 1 + end do + !$acc end parallel + + !$acc data copy(a) + !$acc parallel loop firstprivate(l) default(none) + do i = 1, l + a(1,i) = 1 + end do + !$acc end parallel + !$acc end data +end subroutine acc_parallel_default_none \ No newline at end of file From 7672b0fe65e956dbd3488dfe4ffabe2ab3c6e829 Mon Sep 17 00:00:00 2001 From: Andre Kuhlenschmidt Date: Wed, 27 Aug 2025 14:57:18 -0700 Subject: [PATCH 2/2] address feedback --- flang/lib/Semantics/resolve-directives.cpp | 18 ++++++++---------- flang/test/Semantics/OpenACC/acc-parallel.f90 | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 05efc4f1da910..c3568799c2159 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -61,9 +61,8 @@ template class DirectiveAttributeVisitor { defaultMap; std::optional FindSymbolWithDSA(const Symbol &symbol) { - auto it{objectWithDSA.find(&symbol)}; - if (it != objectWithDSA.end()) { - return std::make_optional(it->second); + if (auto it{objectWithDSA.find(&symbol)}; it != objectWithDSA.end()) { + return it->second; } return std::nullopt; } @@ -83,10 +82,9 @@ template class DirectiveAttributeVisitor { } void PushContext(const parser::CharBlock &source, T dir, Scope &scope) { if constexpr (std::is_same_v) { - bool wasEmpty{dirContext_.empty()}; dirContext_.emplace_back(source, dir, scope); - if (!wasEmpty) { - std::size_t lastIndex{dirContext_.size() - 1}; + if (std::size_t size{dirContext_.size()}; size > 1) { + std::size_t lastIndex{size - 1}; dirContext_[lastIndex].defaultDSA = dirContext_[lastIndex - 1].defaultDSA; } @@ -128,7 +126,7 @@ template class DirectiveAttributeVisitor { return false; } - bool WithinContstruct() { + bool WithinConstruct() { return !dirContext_.empty() && GetContext().withinConstruct; } @@ -1602,7 +1600,7 @@ void AccAttributeVisitor::Post(const parser::AccDefaultClause &x) { // and adjust the symbol for each Name if necessary void AccAttributeVisitor::Post(const parser::Name &name) { auto *symbol{name.symbol}; - if (symbol && WithinContstruct()) { + if (symbol && WithinConstruct()) { symbol = &symbol->GetUltimate(); if (!symbol->owner().IsDerivedType() && !symbol->has() && !symbol->has() && !IsObjectWithVisibleDSA(*symbol)) { @@ -1988,7 +1986,7 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct( // till OpenMP-5.0 standard. // In above both cases we skip the privatization of iteration variables. bool OmpAttributeVisitor::Pre(const parser::DoConstruct &x) { - if (WithinContstruct()) { + if (WithinConstruct()) { llvm::SmallVector ivs; if (x.IsDoNormal()) { const parser::Name *iv{GetLoopIndex(x)}; @@ -2714,7 +2712,7 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) { void OmpAttributeVisitor::Post(const parser::Name &name) { auto *symbol{name.symbol}; - if (symbol && WithinContstruct()) { + if (symbol && WithinConstruct()) { if (IsPrivatizable(symbol) && !IsObjectWithDSA(*symbol)) { // TODO: create a separate function to go through the rules for // predetermined, explicitly determined, and implicitly diff --git a/flang/test/Semantics/OpenACC/acc-parallel.f90 b/flang/test/Semantics/OpenACC/acc-parallel.f90 index 52e267f6910da..45c0fafbed1b6 100644 --- a/flang/test/Semantics/OpenACC/acc-parallel.f90 +++ b/flang/test/Semantics/OpenACC/acc-parallel.f90 @@ -221,4 +221,4 @@ subroutine acc_parallel_default_none end do !$acc end parallel !$acc end data -end subroutine acc_parallel_default_none \ No newline at end of file +end subroutine acc_parallel_default_none