Skip to content

Commit 6768056

Browse files
authored
[flang][openacc] bug fix in semantic checking (#155659)
This fixes two scoping related bugs with OpenACC semantic checking. - Data constructs with open acc now inherit the default Data Sharing Attribute of their parent construct. - Data Sharing Attributes scopes now nest such that if a symbol's DSA wasn't declared by the innermost then lookup looks in the parent construct's data sharing declarations. This fixes the added test cases.
1 parent aa71d95 commit 6768056

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "llvm/Support/Debug.h"
3030
#include <list>
3131
#include <map>
32-
#include <sstream>
3332

3433
template <typename T>
3534
static Fortran::semantics::Scope *GetScope(
@@ -61,6 +60,13 @@ template <typename T> class DirectiveAttributeVisitor {
6160
parser::OmpDefaultmapClause::ImplicitBehavior>
6261
defaultMap;
6362

63+
std::optional<Symbol::Flag> FindSymbolWithDSA(const Symbol &symbol) {
64+
if (auto it{objectWithDSA.find(&symbol)}; it != objectWithDSA.end()) {
65+
return it->second;
66+
}
67+
return std::nullopt;
68+
}
69+
6470
bool withinConstruct{false};
6571
std::int64_t associatedLoopLevel{0};
6672
};
@@ -75,10 +81,19 @@ template <typename T> class DirectiveAttributeVisitor {
7581
: std::make_optional<DirContext>(dirContext_.back());
7682
}
7783
void PushContext(const parser::CharBlock &source, T dir, Scope &scope) {
78-
dirContext_.emplace_back(source, dir, scope);
84+
if constexpr (std::is_same_v<T, llvm::acc::Directive>) {
85+
dirContext_.emplace_back(source, dir, scope);
86+
if (std::size_t size{dirContext_.size()}; size > 1) {
87+
std::size_t lastIndex{size - 1};
88+
dirContext_[lastIndex].defaultDSA =
89+
dirContext_[lastIndex - 1].defaultDSA;
90+
}
91+
} else {
92+
dirContext_.emplace_back(source, dir, scope);
93+
}
7994
}
8095
void PushContext(const parser::CharBlock &source, T dir) {
81-
dirContext_.emplace_back(source, dir, context_.FindScope(source));
96+
PushContext(source, dir, context_.FindScope(source));
8297
}
8398
void PopContext() { dirContext_.pop_back(); }
8499
void SetContextDirectiveSource(parser::CharBlock &dir) {
@@ -100,9 +115,21 @@ template <typename T> class DirectiveAttributeVisitor {
100115
AddToContextObjectWithDSA(symbol, flag, GetContext());
101116
}
102117
bool IsObjectWithDSA(const Symbol &symbol) {
103-
auto it{GetContext().objectWithDSA.find(&symbol)};
104-
return it != GetContext().objectWithDSA.end();
118+
return GetContext().FindSymbolWithDSA(symbol).has_value();
119+
}
120+
bool IsObjectWithVisibleDSA(const Symbol &symbol) {
121+
for (std::size_t i{dirContext_.size()}; i != 0; i--) {
122+
if (dirContext_[i - 1].FindSymbolWithDSA(symbol).has_value()) {
123+
return true;
124+
}
125+
}
126+
return false;
105127
}
128+
129+
bool WithinConstruct() {
130+
return !dirContext_.empty() && GetContext().withinConstruct;
131+
}
132+
106133
void SetContextAssociatedLoopLevel(std::int64_t level) {
107134
GetContext().associatedLoopLevel = level;
108135
}
@@ -1573,10 +1600,10 @@ void AccAttributeVisitor::Post(const parser::AccDefaultClause &x) {
15731600
// and adjust the symbol for each Name if necessary
15741601
void AccAttributeVisitor::Post(const parser::Name &name) {
15751602
auto *symbol{name.symbol};
1576-
if (symbol && !dirContext_.empty() && GetContext().withinConstruct) {
1603+
if (symbol && WithinConstruct()) {
15771604
symbol = &symbol->GetUltimate();
15781605
if (!symbol->owner().IsDerivedType() && !symbol->has<ProcEntityDetails>() &&
1579-
!symbol->has<SubprogramDetails>() && !IsObjectWithDSA(*symbol)) {
1606+
!symbol->has<SubprogramDetails>() && !IsObjectWithVisibleDSA(*symbol)) {
15801607
if (Symbol * found{currScope().FindSymbol(name.source)}) {
15811608
if (symbol != found) {
15821609
name.symbol = found; // adjust the symbol within region
@@ -1959,7 +1986,7 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct(
19591986
// till OpenMP-5.0 standard.
19601987
// In above both cases we skip the privatization of iteration variables.
19611988
bool OmpAttributeVisitor::Pre(const parser::DoConstruct &x) {
1962-
if (!dirContext_.empty() && GetContext().withinConstruct) {
1989+
if (WithinConstruct()) {
19631990
llvm::SmallVector<const parser::Name *> ivs;
19641991
if (x.IsDoNormal()) {
19651992
const parser::Name *iv{GetLoopIndex(x)};
@@ -2685,7 +2712,7 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) {
26852712
void OmpAttributeVisitor::Post(const parser::Name &name) {
26862713
auto *symbol{name.symbol};
26872714

2688-
if (symbol && !dirContext_.empty() && GetContext().withinConstruct) {
2715+
if (symbol && WithinConstruct()) {
26892716
if (IsPrivatizable(symbol) && !IsObjectWithDSA(*symbol)) {
26902717
// TODO: create a separate function to go through the rules for
26912718
// predetermined, explicitly determined, and implicitly

flang/test/Semantics/OpenACC/acc-parallel.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,25 @@ program openacc_parallel_validity
200200
!$acc end parallel
201201

202202
end program openacc_parallel_validity
203+
204+
subroutine acc_parallel_default_none
205+
integer :: i, l
206+
real :: a(10,10)
207+
l = 10
208+
!$acc parallel default(none)
209+
!$acc loop
210+
!ERROR: The DEFAULT(NONE) clause requires that 'l' must be listed in a data-mapping clause
211+
do i = 1, l
212+
!ERROR: The DEFAULT(NONE) clause requires that 'a' must be listed in a data-mapping clause
213+
a(1,i) = 1
214+
end do
215+
!$acc end parallel
216+
217+
!$acc data copy(a)
218+
!$acc parallel loop firstprivate(l) default(none)
219+
do i = 1, l
220+
a(1,i) = 1
221+
end do
222+
!$acc end parallel
223+
!$acc end data
224+
end subroutine acc_parallel_default_none

0 commit comments

Comments
 (0)