[flang-commits] [flang] [flang] Deallocate structure constructor allocatable components (PR #83824)
via flang-commits
flang-commits at lists.llvm.org
Mon Mar 4 03:11:23 PST 2024
https://github.com/jeanPerier created https://github.com/llvm/llvm-project/pull/83824
Allocatable components of structure constructors were not deallocated.
Deallocate them without calling final subroutines.
This was already properly done for array constructors.
>From ca00aa8d62e89ac351300686f43d5458ea72420a Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Mon, 4 Mar 2024 02:27:26 -0800
Subject: [PATCH] [flang] Deallocate structure constructor allocatable
components
Allocatable components of structure constructors were not deallocated.
Deallocate them without calling final subroutines.
This was already properly done for array constructors.
---
flang/docs/Extensions.md | 15 +++++++++++++++
flang/lib/Lower/ConvertExprToHLFIR.cpp | 10 ++++++++++
flang/test/Lower/HLFIR/structure-constructor.f90 | 12 ++++++++++++
3 files changed, 37 insertions(+)
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index baecfd7c48fd06..697bd131c04c7a 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -706,6 +706,21 @@ end
`INDEX` include an optional `BACK=` argument, but it doesn't actually
work.
+* Allocatable components of array and structure constructors are deallocated
+ after use without calling final subroutines.
+ The standard does not specify when and how deallocation of array and structure
+ constructors allocatable components should happen. All compilers free the
+ memory after use, but the behavior when the allocatable component is a derived
+ type with finalization differ, especially when dealing with nested array and
+ structure constructors expressions. Some compilers call final routine for the
+ allocatable components of each constructor sub-expressions, some call it only
+ for the allocatable component of the top level constructor, and some only
+ deallocate the memory. Deallocating only the memory offers the most
+ flexibility when lowering such expressions, and it is not clear finalization
+ is desirable in such context (Fortran interop 1.6.2 in F2018 standards require
+ array and structure constructors not to be finalized, so it also makes sense
+ not to finalize their allocatable components when releasing their storage).
+
## De Facto Standard Features
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 68ecaa19d2d5d1..731c5072c45c58 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1844,6 +1844,16 @@ class HlfirBuilder {
builder.genIfThen(loc, isAlloc).genThen(genAssign).end();
}
+ if (fir::isRecordWithAllocatableMember(recTy)) {
+ // Deallocate allocatable components without calling final subroutines.
+ // The Fortran 2018 section 9.7.3.2 about deallocation is not ruling
+ // about the fate of allocatable components of structure constructors,
+ // and there is no behavior consensus in other compilers.
+ fir::FirOpBuilder *bldr = &builder;
+ getStmtCtx().attachCleanup([=]() {
+ fir::runtime::genDerivedTypeDestroyWithoutFinalization(*bldr, loc, box);
+ });
+ }
return varOp;
}
diff --git a/flang/test/Lower/HLFIR/structure-constructor.f90 b/flang/test/Lower/HLFIR/structure-constructor.f90
index ff0c27f274f32a..d02427d2ff671a 100644
--- a/flang/test/Lower/HLFIR/structure-constructor.f90
+++ b/flang/test/Lower/HLFIR/structure-constructor.f90
@@ -161,6 +161,8 @@ end subroutine test4
! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
! CHECK: }
! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
+! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_27]]
! CHECK: return
! CHECK: }
@@ -201,6 +203,8 @@ end subroutine test5
! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_18]] realloc temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
! CHECK: }
! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
+! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_24]]
! CHECK: return
! CHECK: }
@@ -291,6 +295,10 @@ end subroutine test6
! CHECK: %[[VAL_70:.*]] = hlfir.as_expr %[[VAL_48]]#0 move %[[VAL_69]] : (!fir.heap<!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>>, i1) -> !hlfir.expr<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>
! CHECK: hlfir.assign %[[VAL_70]] to %[[VAL_44]] temporary_lhs : !hlfir.expr<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>>
! CHECK: hlfir.assign %[[VAL_20]]#0 to %[[VAL_12]]#0 : !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>
+! CHECK: %[[VAL_71:.*]] = fir.convert %[[VAL_21]] : (!fir.box<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_71]]
+! CHECK: %[[VAL_72:.*]] = fir.convert %[[VAL_29]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_72]]
! CHECK: return
! CHECK: }
@@ -375,6 +383,8 @@ end subroutine test8
! CHECK: hlfir.assign %[[VAL_29]] to %[[VAL_22]] realloc keep_lhs_len temporary_lhs : !fir.heap<!fir.char<1,12>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
! CHECK: }
! CHECK: hlfir.assign %[[VAL_14]]#0 to %[[VAL_2]]#0 : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
+! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_15]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_30]]
! CHECK: return
! CHECK: }
@@ -410,6 +420,8 @@ end subroutine test9
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_12]]#0{"c"} typeparams %[[VAL_19]] {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.ref<!fir.char<1,12>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_2]]#0 : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
+! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_21]]
! CHECK: return
! CHECK: }
More information about the flang-commits
mailing list