Skip to content

Commit

Permalink
[flang] Set SAVE attribute for EQUIVALENCEd symbols consistently. (#6…
Browse files Browse the repository at this point in the history
…7078)

Example:
```
subroutine global_sub()
  integer, dimension(4) :: iarr4=(/1,2,3,4/)
  integer, dimension(4) :: jarr4
  equivalence(iarr4,jarr4)
  call sub1
  print *, iarr4
contains
  subroutine sub1
    iarr4=jarr4((/4:1:-1/))
  end subroutine sub1
end subroutine global_sub
```

`iarr4` and `jarr4` are equivalenced via a global aggregate storage,
but the references inside `sub1` are lowered differently.
`iarr4` is accessed via the global aggregate storage, while `jarr4`
is accessed via the argument tuple. This confuses the FIR alias
analysis,
that claims that a host associated entity cannot alias with a global
(if they have different source and do not have Target/Pointer
attributes deduced by the alias analysis).

I am not convinced that there is an issue in the alias analysis yet.
I think we'd better lower the accesses uniformly, i.e. if one variable
from an equivalence is lowered via the global aggregate storage, then
any other variable from this equivalence should be lowered the same way
(even if they are used via host association).

This patch makes sure that all symbols from an EQUIVALENCE get
and implicit SAVE attribute, if they do not have it already and
any symbol from the EQUIVALENCE is SAVEd (explicitly or implicitly).
This makes the further lowering consistent.
  • Loading branch information
vzakhari committed Sep 25, 2023
1 parent 0455596 commit e7b8e18
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 18 deletions.
5 changes: 3 additions & 2 deletions flang/lib/Lower/HostAssociations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,12 +508,13 @@ void Fortran::lower::HostAssociations::addSymbolsToBind(
"must be initially empty");
this->hostScope = &hostScope;
for (const auto *s : symbols)
if (Fortran::lower::symbolIsGlobal(*s))
if (Fortran::lower::symbolIsGlobal(*s)) {
// The ultimate symbol is stored here so that global symbols from the
// host scope can later be searched in this set.
globalSymbols.insert(&s->GetUltimate());
else
} else {
tupleSymbols.insert(s);
}
}

void Fortran::lower::HostAssociations::hostProcedureBindings(
Expand Down
12 changes: 6 additions & 6 deletions flang/lib/Semantics/resolve-names-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,17 +353,17 @@ Bound ArraySpecAnalyzer::GetBound(const parser::SpecificationExpr &x) {
return Bound{std::move(expr)};
}

// If SAVE is set on src, set it on all members of dst
// If src is SAVE (explicitly or implicitly),
// set SAVE attribute on all members of dst.
static void PropagateSaveAttr(
const EquivalenceObject &src, EquivalenceSet &dst) {
if (src.symbol.attrs().test(Attr::SAVE)) {
bool isImplicit{src.symbol.implicitAttrs().test(Attr::SAVE)};
if (IsSaved(src.symbol)) {
for (auto &obj : dst) {
if (!obj.symbol.attrs().test(Attr::SAVE)) {
obj.symbol.attrs().set(Attr::SAVE);
if (isImplicit) {
obj.symbol.implicitAttrs().set(Attr::SAVE);
}
// If the other equivalenced symbol itself is not SAVE,
// then adding SAVE here implies that it has to be implicit.
obj.symbol.implicitAttrs().set(Attr::SAVE);
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2391,6 +2391,12 @@ Symbol &ScopeHandler::MakeHostAssocSymbol(
// on the host-associated name, at most once (C815).
symbol.implicitAttrs() =
symbol.attrs() & Attrs{Attr::ASYNCHRONOUS, Attr::VOLATILE};
// SAVE statement in the inner scope will create a new symbol.
// If the host variable is used via host association,
// we have to propagate whether SAVE is implicit in the host scope.
// Otherwise, verifications that do not allow explicit SAVE
// attribute would fail.
symbol.implicitAttrs() |= hostSymbol.implicitAttrs() & Attrs{Attr::SAVE};
symbol.flags() = hostSymbol.flags();
return symbol;
}
Expand Down
195 changes: 195 additions & 0 deletions flang/test/Lower/equivalence-with-host-assoc.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
! RUN: bbc -emit-fir -o - %s | FileCheck %s --check-prefixes=FIR
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=HLFIR

subroutine test1()
integer :: i1 = 1
integer :: j1
equivalence(i1,j1)
contains
subroutine inner
i1 = j1
end subroutine inner
end subroutine test1
! FIR-LABEL: func.func @_QFtest1Pinner() attributes {fir.internal_proc} {
! FIR: %[[VAL_0:.*]] = fir.address_of(@_QFtest1Ei1) : !fir.ref<!fir.array<1xi32>>
! FIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.array<1xi32>>) -> !fir.ref<!fir.array<4xi8>>
! FIR: %[[VAL_2:.*]] = arith.constant 0 : index
! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_5:.*]] = arith.constant 0 : index
! FIR: %[[VAL_6:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_5]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ptr<i32>
! FIR: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ptr<i32>
! FIR: return
! FIR: }

! HLFIR-LABEL: func.func @_QFtest1Pinner() attributes {fir.internal_proc} {
! HLFIR: %[[VAL_0:.*]] = fir.address_of(@_QFtest1Ei1) : !fir.ref<!fir.array<1xi32>>
! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.array<1xi32>>) -> !fir.ref<!fir.array<4xi8>>
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest1Ei1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_6:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_6]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFtest1Ej1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_10:.*]] = fir.load %[[VAL_9]]#0 : !fir.ptr<i32>
! HLFIR: hlfir.assign %[[VAL_10]] to %[[VAL_5]]#0 : i32, !fir.ptr<i32>
! HLFIR: return
! HLFIR: }

module test2
real :: f1, f2
equivalence(f1, f2)
contains
subroutine host
real :: f1 = 1
real :: f2
equivalence(f1, f2)
contains
subroutine inner
f1 = f2
end subroutine inner
end subroutine host
end module test2
! FIR-LABEL: func.func @_QMtest2FhostPinner() attributes {fir.internal_proc} {
! FIR: %[[VAL_0:.*]] = fir.address_of(@_QMtest2FhostEf1) : !fir.ref<!fir.array<1xi32>>
! FIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.array<1xi32>>) -> !fir.ref<!fir.array<4xi8>>
! FIR: %[[VAL_2:.*]] = arith.constant 0 : index
! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<f32>
! FIR: %[[VAL_5:.*]] = arith.constant 0 : index
! FIR: %[[VAL_6:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_5]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (!fir.ref<i8>) -> !fir.ptr<f32>
! FIR: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ptr<f32>
! FIR: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ptr<f32>
! FIR: return
! FIR: }

! HLFIR-LABEL: func.func @_QMtest2FhostPinner() attributes {fir.internal_proc} {
! HLFIR: %[[VAL_0:.*]] = fir.address_of(@_QMtest2FhostEf1) : !fir.ref<!fir.array<1xi32>>
! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.array<1xi32>>) -> !fir.ref<!fir.array<4xi8>>
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<f32>
! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMtest2FhostEf1"} : (!fir.ptr<f32>) -> (!fir.ptr<f32>, !fir.ptr<f32>)
! HLFIR: %[[VAL_6:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_6]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<i8>) -> !fir.ptr<f32>
! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QMtest2FhostEf2"} : (!fir.ptr<f32>) -> (!fir.ptr<f32>, !fir.ptr<f32>)
! HLFIR: %[[VAL_19:.*]] = fir.load %[[VAL_9]]#0 : !fir.ptr<f32>
! HLFIR: hlfir.assign %[[VAL_19]] to %[[VAL_5]]#0 : f32, !fir.ptr<f32>
! HLFIR: return
! HLFIR: }

subroutine test3()
integer :: i1 = 1
integer :: j1, k1
common /blk/ k1
equivalence(i1,j1,k1)
contains
subroutine inner
i1 = j1 + k1
end subroutine inner
end subroutine test3
! FIR-LABEL: func.func @_QFtest3Pinner() attributes {fir.internal_proc} {
! FIR: %[[VAL_0:.*]] = fir.address_of(@blk_) : !fir.ref<tuple<i32>>
! FIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! FIR: %[[VAL_2:.*]] = arith.constant 0 : index
! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_5:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! FIR: %[[VAL_6:.*]] = arith.constant 0 : index
! FIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_5]], %[[VAL_6]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! FIR: %[[VAL_10:.*]] = arith.constant 0 : index
! FIR: %[[VAL_11:.*]] = fir.coordinate_of %[[VAL_9]], %[[VAL_10]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_13:.*]] = fir.load %[[VAL_8]] : !fir.ptr<i32>
! FIR: %[[VAL_14:.*]] = fir.load %[[VAL_12]] : !fir.ptr<i32>
! FIR: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32
! FIR: fir.store %[[VAL_15]] to %[[VAL_4]] : !fir.ptr<i32>
! FIR: return
! FIR: }

! HLFIR-LABEL: func.func @_QFtest3Pinner() attributes {fir.internal_proc} {
! HLFIR: %[[VAL_0:.*]] = fir.address_of(@blk_) : !fir.ref<tuple<i32>>
! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest3Ei1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_6:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! HLFIR: %[[VAL_7:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_6]], %[[VAL_7]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] {uniq_name = "_QFtest3Ej1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_11:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! HLFIR: %[[VAL_12:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_11]], %[[VAL_12]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFtest3Ek1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_16:.*]] = fir.load %[[VAL_10]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_17:.*]] = fir.load %[[VAL_15]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
! HLFIR: hlfir.assign %[[VAL_18]] to %[[VAL_5]]#0 : i32, !fir.ptr<i32>
! HLFIR: return
! HLFIR: }

subroutine test4()
integer :: i1
integer :: j1, k1
common /blk/ k1
equivalence(i1,j1,k1)
contains
subroutine inner
i1 = j1 + k1
end subroutine inner
end subroutine test4
! FIR-LABEL: func.func @_QFtest4Pinner() attributes {fir.internal_proc} {
! FIR: %[[VAL_0:.*]] = fir.address_of(@blk_) : !fir.ref<tuple<i32>>
! FIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! FIR: %[[VAL_2:.*]] = arith.constant 0 : index
! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_5:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! FIR: %[[VAL_6:.*]] = arith.constant 0 : index
! FIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_5]], %[[VAL_6]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! FIR: %[[VAL_10:.*]] = arith.constant 0 : index
! FIR: %[[VAL_11:.*]] = fir.coordinate_of %[[VAL_9]], %[[VAL_10]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! FIR: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! FIR: %[[VAL_13:.*]] = fir.load %[[VAL_8]] : !fir.ptr<i32>
! FIR: %[[VAL_14:.*]] = fir.load %[[VAL_12]] : !fir.ptr<i32>
! FIR: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32
! FIR: fir.store %[[VAL_15]] to %[[VAL_4]] : !fir.ptr<i32>
! FIR: return
! FIR: }

! HLFIR-LABEL: func.func @_QFtest4Pinner() attributes {fir.internal_proc} {
! HLFIR: %[[VAL_0:.*]] = fir.address_of(@blk_) : !fir.ref<tuple<i32>>
! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest4Ei1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_6:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! HLFIR: %[[VAL_7:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_6]], %[[VAL_7]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] {uniq_name = "_QFtest4Ej1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_11:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<?xi8>>
! HLFIR: %[[VAL_12:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_11]], %[[VAL_12]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<i8>) -> !fir.ptr<i32>
! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFtest4Ek1"} : (!fir.ptr<i32>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_16:.*]] = fir.load %[[VAL_10]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_17:.*]] = fir.load %[[VAL_15]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
! HLFIR: hlfir.assign %[[VAL_18]] to %[[VAL_5]]#0 : i32, !fir.ptr<i32>
! HLFIR: return
! HLFIR: }
4 changes: 2 additions & 2 deletions flang/test/Semantics/data13.f90
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
! initialization produces a combined initializer, with explicit
! initialization overriding any default component initialization.
! CHECK: .F18.0, SAVE (CompilerCreated) size=8 offset=0: ObjectEntity type: INTEGER(4) shape: 1_8:2_8 init:[INTEGER(4)::456_4,234_4]
! CHECK: ja (InDataStmt) size=8 offset=0: ObjectEntity type: INTEGER(4) shape: 1_8:2_8
! CHECK: ja, SAVE (InDataStmt) size=8 offset=0: ObjectEntity type: INTEGER(4) shape: 1_8:2_8
! CHECK-NOT: x0, SAVE size=8 offset=8: ObjectEntity type: TYPE(t1) init:t1(m=123_4,n=234_4)
! CHECK: x1 size=8 offset=16: ObjectEntity type: TYPE(t1) init:t1(m=345_4,n=234_4)
! CHECK: x2 size=8 offset=0: ObjectEntity type: TYPE(t1)
! CHECK: x2, SAVE size=8 offset=0: ObjectEntity type: TYPE(t1)
! CHECK-NOT: x3a, SAVE size=8 offset=24: ObjectEntity type: TYPE(t3) init:t3(t2=t2(k=567_4),j=0_4)
! CHECK: x3b size=8 offset=32: ObjectEntity type: TYPE(t3) init:t3(k=567_4,j=678_4)
! CHECK: Equivalence Sets: (x2,ja(1)) (.F18.0,x2)
Expand Down
16 changes: 8 additions & 8 deletions flang/test/Semantics/offsets03.f90
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
! a1 depends on a2 depends on a3
module ma
real :: a1(10), a2(10), a3(10)
equivalence(a1, a2(3)) !CHECK: a1, PUBLIC size=40 offset=20:
equivalence(a2, a3(4)) !CHECK: a2, PUBLIC size=40 offset=12:
!CHECK: a3, PUBLIC size=40 offset=0:
equivalence(a1, a2(3)) !CHECK: a1, PUBLIC, SAVE size=40 offset=20:
equivalence(a2, a3(4)) !CHECK: a2, PUBLIC, SAVE size=40 offset=12:
!CHECK: a3, PUBLIC, SAVE size=40 offset=0:
end

! equivalence and 2-dimensional array
module mb
real :: b1(4), b2, b3, b4
real :: b(-1:1,2:6) !CHECK: b, PUBLIC size=60 offset=0:
equivalence(b(1,6), b1) !CHECK: b1, PUBLIC size=16 offset=56:
equivalence(b(1,5), b2) !CHECK: b2, PUBLIC size=4 offset=44:
equivalence(b(0,6), b3) !CHECK: b3, PUBLIC size=4 offset=52:
equivalence(b(0,4), b4) !CHECK: b4, PUBLIC size=4 offset=28:
real :: b(-1:1,2:6) !CHECK: b, PUBLIC, SAVE size=60 offset=0:
equivalence(b(1,6), b1) !CHECK: b1, PUBLIC, SAVE size=16 offset=56:
equivalence(b(1,5), b2) !CHECK: b2, PUBLIC, SAVE size=4 offset=44:
equivalence(b(0,6), b3) !CHECK: b3, PUBLIC, SAVE size=4 offset=52:
equivalence(b(0,4), b4) !CHECK: b4, PUBLIC, SAVE size=4 offset=28:
end

! equivalence and substring
Expand Down
45 changes: 45 additions & 0 deletions flang/test/Semantics/resolve121.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
! Check that symbols without SAVE attribute from an EQUIVALENCE
! with at least one symbol being SAVEd (explicitly or implicitly)
! have implicit SAVE attribute.
!RUN: %flang_fc1 -fdebug-dump-symbols %s | FileCheck %s

subroutine test1()
! CHECK-LABEL: Subprogram scope: test1
! CHECK: i1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4) init:1_4
! CHECK: j1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4)
integer :: i1 = 1
integer :: j1
equivalence(i1,j1)
end subroutine test1

subroutine test2()
! CHECK-LABEL: Subprogram scope: test2
! CHECK: i1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4) init:1_4
! CHECK: j1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4)
integer :: i1 = 1
integer :: j1
equivalence(j1,i1)
end subroutine test2

subroutine test3()
! CHECK-LABEL: Subprogram scope: test3
! CHECK: i1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4)
! CHECK: j1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4)
! CHECK: k1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4)
integer :: i1
integer :: j1, k1
common /blk/ k1
save /blk/
equivalence(i1,j1,k1)
end subroutine test3

subroutine test4()
! CHECK-LABEL: Subprogram scope: test4
! CHECK: i1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4) init:1_4
! CHECK: j1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4)
! CHECK: k1, SAVE size=4 offset=0: ObjectEntity type: INTEGER(4)
integer :: i1 = 1
integer :: j1, k1
common /blk/ k1
equivalence(i1,j1,k1)
end subroutine test4

0 comments on commit e7b8e18

Please sign in to comment.