diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp index aa0cc50b6347a..a62f7a7e99b6f 100644 --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -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( diff --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp index 2f8e5777c5290..ebc7aab3744d5 100644 --- a/flang/lib/Semantics/resolve-names-utils.cpp +++ b/flang/lib/Semantics/resolve-names-utils.cpp @@ -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); } } } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 60a604bd08888..303840b00f8f2 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -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; } diff --git a/flang/test/Lower/equivalence-with-host-assoc.f90 b/flang/test/Lower/equivalence-with-host-assoc.f90 new file mode 100644 index 0000000000000..e69b08106aa6d --- /dev/null +++ b/flang/test/Lower/equivalence-with-host-assoc.f90 @@ -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: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_2:.*]] = arith.constant 0 : index +! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_5:.*]] = arith.constant 0 : index +! FIR: %[[VAL_6:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_5]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ptr +! FIR: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ptr +! FIR: return +! FIR: } + +! HLFIR-LABEL: func.func @_QFtest1Pinner() attributes {fir.internal_proc} { +! HLFIR: %[[VAL_0:.*]] = fir.address_of(@_QFtest1Ei1) : !fir.ref> +! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest1Ei1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_6:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_6]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFtest1Ej1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_10:.*]] = fir.load %[[VAL_9]]#0 : !fir.ptr +! HLFIR: hlfir.assign %[[VAL_10]] to %[[VAL_5]]#0 : i32, !fir.ptr +! 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: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_2:.*]] = arith.constant 0 : index +! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_5:.*]] = arith.constant 0 : index +! FIR: %[[VAL_6:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_5]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ptr +! FIR: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ptr +! FIR: return +! FIR: } + +! HLFIR-LABEL: func.func @_QMtest2FhostPinner() attributes {fir.internal_proc} { +! HLFIR: %[[VAL_0:.*]] = fir.address_of(@_QMtest2FhostEf1) : !fir.ref> +! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMtest2FhostEf1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_6:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_6]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QMtest2FhostEf2"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_19:.*]] = fir.load %[[VAL_9]]#0 : !fir.ptr +! HLFIR: hlfir.assign %[[VAL_19]] to %[[VAL_5]]#0 : f32, !fir.ptr +! 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> +! FIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_2:.*]] = arith.constant 0 : index +! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_5:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_6:.*]] = arith.constant 0 : index +! FIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_5]], %[[VAL_6]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_10:.*]] = arith.constant 0 : index +! FIR: %[[VAL_11:.*]] = fir.coordinate_of %[[VAL_9]], %[[VAL_10]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_13:.*]] = fir.load %[[VAL_8]] : !fir.ptr +! FIR: %[[VAL_14:.*]] = fir.load %[[VAL_12]] : !fir.ptr +! FIR: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! FIR: fir.store %[[VAL_15]] to %[[VAL_4]] : !fir.ptr +! FIR: return +! FIR: } + +! HLFIR-LABEL: func.func @_QFtest3Pinner() attributes {fir.internal_proc} { +! HLFIR: %[[VAL_0:.*]] = fir.address_of(@blk_) : !fir.ref> +! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest3Ei1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_6:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_7:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_6]], %[[VAL_7]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] {uniq_name = "_QFtest3Ej1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_11:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_12:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_11]], %[[VAL_12]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFtest3Ek1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_16:.*]] = fir.load %[[VAL_10]]#0 : !fir.ptr +! HLFIR: %[[VAL_17:.*]] = fir.load %[[VAL_15]]#0 : !fir.ptr +! HLFIR: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32 +! HLFIR: hlfir.assign %[[VAL_18]] to %[[VAL_5]]#0 : i32, !fir.ptr +! 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> +! FIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_2:.*]] = arith.constant 0 : index +! FIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_5:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_6:.*]] = arith.constant 0 : index +! FIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_5]], %[[VAL_6]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! FIR: %[[VAL_10:.*]] = arith.constant 0 : index +! FIR: %[[VAL_11:.*]] = fir.coordinate_of %[[VAL_9]], %[[VAL_10]] : (!fir.ref>, index) -> !fir.ref +! FIR: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (!fir.ref) -> !fir.ptr +! FIR: %[[VAL_13:.*]] = fir.load %[[VAL_8]] : !fir.ptr +! FIR: %[[VAL_14:.*]] = fir.load %[[VAL_12]] : !fir.ptr +! FIR: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! FIR: fir.store %[[VAL_15]] to %[[VAL_4]] : !fir.ptr +! FIR: return +! FIR: } + +! HLFIR-LABEL: func.func @_QFtest4Pinner() attributes {fir.internal_proc} { +! HLFIR: %[[VAL_0:.*]] = fir.address_of(@blk_) : !fir.ref> +! HLFIR: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest4Ei1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_6:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_7:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_6]], %[[VAL_7]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] {uniq_name = "_QFtest4Ej1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_11:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! HLFIR: %[[VAL_12:.*]] = arith.constant 0 : index +! HLFIR: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_11]], %[[VAL_12]] : (!fir.ref>, index) -> !fir.ref +! HLFIR: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref) -> !fir.ptr +! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFtest4Ek1"} : (!fir.ptr) -> (!fir.ptr, !fir.ptr) +! HLFIR: %[[VAL_16:.*]] = fir.load %[[VAL_10]]#0 : !fir.ptr +! HLFIR: %[[VAL_17:.*]] = fir.load %[[VAL_15]]#0 : !fir.ptr +! HLFIR: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32 +! HLFIR: hlfir.assign %[[VAL_18]] to %[[VAL_5]]#0 : i32, !fir.ptr +! HLFIR: return +! HLFIR: } diff --git a/flang/test/Semantics/data13.f90 b/flang/test/Semantics/data13.f90 index 75e572e0dbc2f..bed61694c94bb 100644 --- a/flang/test/Semantics/data13.f90 +++ b/flang/test/Semantics/data13.f90 @@ -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) diff --git a/flang/test/Semantics/offsets03.f90 b/flang/test/Semantics/offsets03.f90 index 7416b6d3f37d4..c8c1abebb5d3c 100644 --- a/flang/test/Semantics/offsets03.f90 +++ b/flang/test/Semantics/offsets03.f90 @@ -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 diff --git a/flang/test/Semantics/resolve121.f90 b/flang/test/Semantics/resolve121.f90 new file mode 100644 index 0000000000000..d84bc53a50f7c --- /dev/null +++ b/flang/test/Semantics/resolve121.f90 @@ -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