diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 3c59085812989..c3568799c2159 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,13 @@ template class DirectiveAttributeVisitor { parser::OmpDefaultmapClause::ImplicitBehavior> defaultMap; + std::optional FindSymbolWithDSA(const Symbol &symbol) { + if (auto it{objectWithDSA.find(&symbol)}; it != objectWithDSA.end()) { + return it->second; + } + return std::nullopt; + } + bool withinConstruct{false}; std::int64_t associatedLoopLevel{0}; }; @@ -75,10 +81,19 @@ 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) { + dirContext_.emplace_back(source, dir, scope); + if (std::size_t size{dirContext_.size()}; size > 1) { + std::size_t lastIndex{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 +115,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 WithinConstruct() { + return !dirContext_.empty() && GetContext().withinConstruct; + } + void SetContextAssociatedLoopLevel(std::int64_t level) { GetContext().associatedLoopLevel = level; } @@ -1573,10 +1600,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 && WithinConstruct()) { 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 +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 (!dirContext_.empty() && GetContext().withinConstruct) { + if (WithinConstruct()) { llvm::SmallVector ivs; if (x.IsDoNormal()) { const parser::Name *iv{GetLoopIndex(x)}; @@ -2685,7 +2712,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 && 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 635c547f744c8..45c0fafbed1b6 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