Skip to content

Commit 4cb91e7

Browse files
[flang][OpenACC] Relax COMMON block usage restriction in OpenACC directives (llvm#162659)
Unlike OpenMP, OpenACC doesn't require that the COMMON block be defined in the same scope as the directive.
1 parent 3728ac7 commit 4cb91e7

File tree

5 files changed

+129
-22
lines changed

5 files changed

+129
-22
lines changed

flang/include/flang/Semantics/scope.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ class Scope {
8686
CHECK(parent_ != this);
8787
return *parent_;
8888
}
89+
90+
mapType &commonBlocks() { return commonBlocks_; }
91+
const mapType &commonBlocks() const { return commonBlocks_; }
92+
93+
mapType &commonBlockUses() { return commonBlockUses_; }
94+
const mapType &commonBlockUses() const { return commonBlockUses_; }
95+
8996
Kind kind() const { return kind_; }
9097
bool IsGlobal() const { return kind_ == Kind::Global; }
9198
bool IsIntrinsicModules() const { return kind_ == Kind::IntrinsicModules; }
@@ -186,10 +193,19 @@ class Scope {
186193
// Cray pointers are saved as map of pointee name -> pointer symbol
187194
const mapType &crayPointers() const { return crayPointers_; }
188195
void add_crayPointer(const SourceName &, Symbol &);
189-
mapType &commonBlocks() { return commonBlocks_; }
190-
const mapType &commonBlocks() const { return commonBlocks_; }
191196
Symbol &MakeCommonBlock(SourceName, SourceName location);
192-
Symbol *FindCommonBlock(const SourceName &) const;
197+
bool AddCommonBlockUse(
198+
const SourceName &name, Attrs attrs, Symbol &cbUltimate);
199+
200+
// Find COMMON block that is declared in the current scope
201+
Symbol *FindCommonBlock(const SourceName &name) const;
202+
203+
// Find USE-associated COMMON block in the current scope
204+
Symbol *FindCommonBlockUse(const SourceName &name) const;
205+
206+
// Find COMMON block in current and surrounding scopes, follow USE
207+
// associations
208+
Symbol *FindCommonBlockInVisibleScopes(const SourceName &) const;
193209

194210
/// Make a Symbol but don't add it to the scope.
195211
template <typename D>
@@ -283,6 +299,7 @@ class Scope {
283299
std::list<Scope> children_;
284300
mapType symbols_;
285301
mapType commonBlocks_;
302+
mapType commonBlockUses_; // USE-assocated COMMON blocks
286303
std::list<EquivalenceSet> equivalenceSets_;
287304
mapType crayPointers_;
288305
std::map<SourceName, common::Reference<Scope>> submodules_;

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,17 +1723,12 @@ void AccAttributeVisitor::Post(const parser::Name &name) {
17231723

17241724
Symbol *AccAttributeVisitor::ResolveAccCommonBlockName(
17251725
const parser::Name *name) {
1726-
if (auto *prev{name
1727-
? GetContext().scope.parent().FindCommonBlock(name->source)
1728-
: nullptr}) {
1729-
name->symbol = prev;
1730-
return prev;
1731-
}
1732-
// Check if the Common Block is declared in the current scope
1733-
if (auto *commonBlockSymbol{
1734-
name ? GetContext().scope.FindCommonBlock(name->source) : nullptr}) {
1735-
name->symbol = commonBlockSymbol;
1736-
return commonBlockSymbol;
1726+
if (name) {
1727+
if (Symbol *
1728+
cb{GetContext().scope.FindCommonBlockInVisibleScopes(name->source)}) {
1729+
name->symbol = cb;
1730+
return cb;
1731+
}
17371732
}
17381733
return nullptr;
17391734
}
@@ -1783,8 +1778,8 @@ void AccAttributeVisitor::ResolveAccObject(
17831778
}
17841779
} else {
17851780
context_.Say(name.source,
1786-
"COMMON block must be declared in the same scoping unit "
1787-
"in which the OpenACC directive or clause appears"_err_en_US);
1781+
"Could not find COMMON block '%s' used in OpenACC directive"_err_en_US,
1782+
name.ToString());
17881783
}
17891784
},
17901785
},

flang/lib/Semantics/resolve-names.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,6 +3645,20 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
36453645
}
36463646
}
36473647
}
3648+
// Go through the list of COMMON block symbols in the module scope and add
3649+
// their USE association to the current scope's USE-associated COMMON blocks.
3650+
for (const auto &[name, symbol] : useModuleScope_->commonBlocks()) {
3651+
if (!currScope().FindCommonBlockInVisibleScopes(name)) {
3652+
currScope().AddCommonBlockUse(
3653+
name, symbol->attrs(), symbol->GetUltimate());
3654+
}
3655+
}
3656+
// Go through the list of USE-associated COMMON block symbols in the module
3657+
// scope and add USE associations to their ultimate symbols to the current
3658+
// scope's USE-associated COMMON blocks.
3659+
for (const auto &[name, symbol] : useModuleScope_->commonBlockUses()) {
3660+
currScope().AddCommonBlockUse(name, symbol->attrs(), symbol->GetUltimate());
3661+
}
36483662
useModuleScope_ = nullptr;
36493663
}
36503664

flang/lib/Semantics/scope.cpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,34 @@ void Scope::add_crayPointer(const SourceName &name, Symbol &pointer) {
144144
}
145145

146146
Symbol &Scope::MakeCommonBlock(SourceName name, SourceName location) {
147-
const auto it{commonBlocks_.find(name)};
148-
if (it != commonBlocks_.end()) {
149-
return *it->second;
147+
if (auto *cb{FindCommonBlock(name)}) {
148+
return *cb;
150149
} else {
151150
Symbol &symbol{MakeSymbol(
152151
name, Attrs{}, CommonBlockDetails{name.empty() ? location : name})};
153152
commonBlocks_.emplace(name, symbol);
154153
return symbol;
155154
}
156155
}
157-
Symbol *Scope::FindCommonBlock(const SourceName &name) const {
158-
const auto it{commonBlocks_.find(name)};
159-
return it != commonBlocks_.end() ? &*it->second : nullptr;
156+
157+
Symbol *Scope::FindCommonBlockInVisibleScopes(const SourceName &name) const {
158+
if (Symbol * cb{FindCommonBlock(name)}) {
159+
return cb;
160+
} else if (Symbol * cb{FindCommonBlockUse(name)}) {
161+
return &cb->GetUltimate();
162+
} else if (IsSubmodule()) {
163+
if (const Scope *parent{
164+
symbol_ ? symbol_->get<ModuleDetails>().parent() : nullptr}) {
165+
if (auto *cb{parent->FindCommonBlockInVisibleScopes(name)}) {
166+
return cb;
167+
}
168+
}
169+
} else if (!IsTopLevel() && parent_) {
170+
if (auto *cb{parent_->FindCommonBlockInVisibleScopes(name)}) {
171+
return cb;
172+
}
173+
}
174+
return nullptr;
160175
}
161176

162177
Scope *Scope::FindSubmodule(const SourceName &name) const {
@@ -167,6 +182,31 @@ Scope *Scope::FindSubmodule(const SourceName &name) const {
167182
return &*it->second;
168183
}
169184
}
185+
186+
bool Scope::AddCommonBlockUse(
187+
const SourceName &name, Attrs attrs, Symbol &cbUltimate) {
188+
CHECK(cbUltimate.has<CommonBlockDetails>());
189+
// Make a symbol, but don't add it to the Scope, since it needs to
190+
// be added to the USE-associated COMMON blocks
191+
Symbol &useCB{MakeSymbol(name, attrs, UseDetails{name, cbUltimate})};
192+
return commonBlockUses_.emplace(name, useCB).second;
193+
}
194+
195+
Symbol *Scope::FindCommonBlock(const SourceName &name) const {
196+
if (const auto it{commonBlocks_.find(name)}; it != commonBlocks_.end()) {
197+
return &*it->second;
198+
}
199+
return nullptr;
200+
}
201+
202+
Symbol *Scope::FindCommonBlockUse(const SourceName &name) const {
203+
if (const auto it{commonBlockUses_.find(name)};
204+
it != commonBlockUses_.end()) {
205+
return &*it->second;
206+
}
207+
return nullptr;
208+
}
209+
170210
bool Scope::AddSubmodule(const SourceName &name, Scope &submodule) {
171211
return submodules_.emplace(name, submodule).second;
172212
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
! RUN: %python %S/../test_errors.py %s %flang -fopenacc
2+
module acc_common_decl
3+
implicit none
4+
integer a
5+
common /a_common/ a
6+
!$acc declare create (/a_common/)
7+
data a/42/
8+
end module acc_common_decl
9+
10+
module acc_common_another
11+
implicit none
12+
integer c, d
13+
common /a_common/ c, d
14+
!$acc declare create (/a_common/)
15+
end module acc_common_another
16+
17+
module acc_common_intermediate
18+
use acc_common_decl
19+
implicit none
20+
integer b
21+
common /b_common/ b
22+
!$acc declare create (/b_common/)
23+
end module acc_common_intermediate
24+
25+
program acc_decl_test
26+
use acc_common_intermediate
27+
use acc_common_another
28+
implicit none
29+
30+
a = 1
31+
b = 10
32+
!$acc update device (/a_common/)
33+
a = 2
34+
!$acc update device (/b_common/)
35+
b = 20
36+
!$acc update device (/a_common/)
37+
c = 3
38+
d = 30
39+
!ERROR: Could not find COMMON block 'a_common_bad' used in OpenACC directive
40+
!$acc update device (/a_common_bad/)
41+
end program

0 commit comments

Comments
 (0)