Skip to content

Commit 94b4a98

Browse files
authored
[flang] Fix bogus error w/ COMMON & EQUIVALENCE (#66254)
Semantic checking of COMMON blocks and EQUIVALENCE sets has an assumption that the base storage sequence object of each COMMON block object will also be in that COMMON block's list of objects, and emits an error message when this is not the case. This assumption is faulty; it is possible for a base object to have its COMMON block set during offset assignment. Fixes #65922.
1 parent 1212d1b commit 94b4a98

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

flang/lib/Semantics/compute-offsets.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
152152
alignment_ = 0;
153153
std::size_t minSize{0};
154154
std::size_t minAlignment{0};
155-
for (auto &object : details.objects()) {
155+
UnorderedSymbolSet previous;
156+
for (auto object : details.objects()) {
156157
Symbol &symbol{*object};
157158
auto errorSite{
158159
commonBlock.name().empty() ? symbol.name() : commonBlock.name()};
@@ -161,6 +162,7 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
161162
"COMMON block /%s/ requires %zd bytes of padding before '%s' for alignment"_port_en_US,
162163
commonBlock.name(), padding, symbol.name());
163164
}
165+
previous.emplace(symbol);
164166
auto eqIter{equivalenceBlock_.end()};
165167
auto iter{dependents_.find(symbol)};
166168
if (iter == dependents_.end()) {
@@ -173,13 +175,13 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
173175
Symbol &base{*dep.symbol};
174176
if (const auto *baseBlock{FindCommonBlockContaining(base)}) {
175177
if (baseBlock == &commonBlock) {
176-
if (base.offset() != symbol.offset() - dep.offset ||
177-
llvm::is_contained(details.objects(), base)) {
178+
if (previous.find(SymbolRef{base}) == previous.end() ||
179+
base.offset() != symbol.offset() - dep.offset) {
178180
context_.Say(errorSite,
179181
"'%s' is storage associated with '%s' by EQUIVALENCE elsewhere in COMMON block /%s/"_err_en_US,
180182
symbol.name(), base.name(), commonBlock.name());
181183
}
182-
} else { // 8.10.3(1)
184+
} else { // F'2023 8.10.3 p1
183185
context_.Say(errorSite,
184186
"'%s' in COMMON block /%s/ must not be storage associated with '%s' in COMMON block /%s/ by EQUIVALENCE"_err_en_US,
185187
symbol.name(), commonBlock.name(), base.name(),
@@ -193,6 +195,7 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
193195
eqIter = equivalenceBlock_.find(base);
194196
base.get<ObjectEntityDetails>().set_commonBlock(commonBlock);
195197
base.set_offset(symbol.offset() - dep.offset);
198+
previous.emplace(base);
196199
}
197200
}
198201
// Get full extent of any EQUIVALENCE block into size of COMMON ( see

flang/test/Semantics/block-data01.f90

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@ block data foo
3232
integer :: inCommonF1, inCommonF2
3333
!ERROR: 'incommonf1' is storage associated with 'incommonf2' by EQUIVALENCE elsewhere in COMMON block /f/
3434
common /f/ inCommonF1, inCommonF2
35+
!Regression test for llvm-project/issues/65922 - no error expected
36+
common /g/ inCommonG1, inCommonG2
37+
real inCommonG1(-9:10), inCommonG2(10), otherG(11)
38+
equivalence (inCommonG1(1), otherG), (otherG(11), inCommonG2)
3539
end block data

0 commit comments

Comments
 (0)