Skip to content

Commit

Permalink
[flang] Extend common block size to cover equivalence storage
Browse files Browse the repository at this point in the history
The size of common block should be extended to cover any storage
sequence that are storage associated with the common block via
equivalences (8.10.2.2 point 1 (2)).

In symbol size and offset computation, the size of the common block
was not always extended to cover storage association. It was only done
if the "base symbol of an equivalence group"(*) appeared in a common block
statement. Correct this to cover all cases where a symbol appearing in a
common block statement is storage associated.

(*) the base symbol of an equivalence group is the symbol whose storage
starts first in a storage association (if several symbols starts first,
the base symbol is the last one visited by the algorithm going through
the equivalence sets).

Differential Revision: https://reviews.llvm.org/D109156
  • Loading branch information
jeanPerier committed Sep 3, 2021
1 parent 0f80961 commit 084d8be
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
19 changes: 12 additions & 7 deletions flang/lib/Semantics/compute-offsets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,12 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
for (auto &object : details.objects()) {
Symbol &symbol{*object};
DoSymbol(symbol);
auto eqIter{equivalenceBlock_.end()};
auto iter{dependents_.find(symbol)};
if (iter == dependents_.end()) {
// Get full extent of any EQUIVALENCE block into size of COMMON
auto eqIter{equivalenceBlock_.find(symbol)};
auto eqIter = equivalenceBlock_.find(symbol);
if (eqIter != equivalenceBlock_.end()) {
SizeAndAlignment &blockInfo{eqIter->second};
DoEquivalenceBlockBase(symbol, blockInfo);
minSize = std::max(
minSize, std::max(offset_, symbol.offset() + blockInfo.size));
minAlignment = std::max(minAlignment, blockInfo.alignment);
DoEquivalenceBlockBase(symbol, eqIter->second);
}
} else {
SymbolAndOffset &dep{iter->second};
Expand All @@ -183,10 +179,19 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
"'%s' cannot backward-extend COMMON block /%s/ via EQUIVALENCE with '%s'"_err_en_US,
symbol.name(), commonBlock.name(), base.name());
} else {
eqIter = equivalenceBlock_.find(base);
base.get<ObjectEntityDetails>().set_commonBlock(commonBlock);
base.set_offset(symbol.offset() - dep.offset);
}
}
// Get full extent of any EQUIVALENCE block into size of COMMON ( see
// 8.10.2.2 point 1 (2))
if (eqIter != equivalenceBlock_.end()) {
SizeAndAlignment &blockInfo{eqIter->second};
minSize = std::max(
minSize, std::max(offset_, eqIter->first->offset() + blockInfo.size));
minAlignment = std::max(minAlignment, blockInfo.alignment);
}
}
commonBlock.set_size(std::max(minSize, offset_));
details.set_alignment(std::max(minAlignment, alignment_));
Expand Down
20 changes: 20 additions & 0 deletions flang/test/Semantics/offsets03.f90
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,23 @@ module md !CHECK: Module scope: md size=1 alignment=1
common /common1/ d3,d2,d1 !CHECK: common1 size=10 offset=0: CommonBlockDetails alignment=4:
common /common2/ d4 !CHECK: common2 size=2 offset=0: CommonBlockDetails alignment=2:
end

! Test extension of common block size through equivalence statements.
module me
integer :: i1, j1, l1(10)
equivalence(i1, l1)
common /common3/ j1, i1 ! CHECK: common3 size=44 offset=0: CommonBlockDetails alignment=4:

integer :: i2, j2, l2(10)
equivalence(i2, l2(2))
common /common4/ j2, i2 ! CHECK: common4 size=40 offset=0: CommonBlockDetails alignment=4:

integer :: i3, j3, l3(10)
equivalence(i3, l3)
common /common5/ i3, j3 ! CHECK: common5 size=40 offset=0: CommonBlockDetails alignment=4:

integer :: i4, j4, l4(10), k4(10)
equivalence(i4, l4)
equivalence(l4(10), k4)
common /common6/ i4, j4 ! CHECK: common6 size=76 offset=0: CommonBlockDetails alignment=4:
end

0 comments on commit 084d8be

Please sign in to comment.