Skip to content

Commit 74dfded

Browse files
authored
[flang] Deallocate structure constructor allocatable components (#83824)
Allocatable components of structure constructors were not deallocated. Deallocate them without calling final subroutines. This was already properly done for array constructors.
1 parent ad5aea3 commit 74dfded

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

flang/docs/Extensions.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,21 @@ end
706706
`INDEX` include an optional `BACK=` argument, but it doesn't actually
707707
work.
708708

709+
* Allocatable components of array and structure constructors are deallocated
710+
after use without calling final subroutines.
711+
The standard does not specify when and how deallocation of array and structure
712+
constructors allocatable components should happen. All compilers free the
713+
memory after use, but the behavior when the allocatable component is a derived
714+
type with finalization differ, especially when dealing with nested array and
715+
structure constructors expressions. Some compilers call final routine for the
716+
allocatable components of each constructor sub-expressions, some call it only
717+
for the allocatable component of the top level constructor, and some only
718+
deallocate the memory. Deallocating only the memory offers the most
719+
flexibility when lowering such expressions, and it is not clear finalization
720+
is desirable in such context (Fortran interop 1.6.2 in F2018 standards require
721+
array and structure constructors not to be finalized, so it also makes sense
722+
not to finalize their allocatable components when releasing their storage).
723+
709724
## De Facto Standard Features
710725

711726
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the

flang/lib/Lower/ConvertExprToHLFIR.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,6 +1844,16 @@ class HlfirBuilder {
18441844
builder.genIfThen(loc, isAlloc).genThen(genAssign).end();
18451845
}
18461846

1847+
if (fir::isRecordWithAllocatableMember(recTy)) {
1848+
// Deallocate allocatable components without calling final subroutines.
1849+
// The Fortran 2018 section 9.7.3.2 about deallocation is not ruling
1850+
// about the fate of allocatable components of structure constructors,
1851+
// and there is no behavior consensus in other compilers.
1852+
fir::FirOpBuilder *bldr = &builder;
1853+
getStmtCtx().attachCleanup([=]() {
1854+
fir::runtime::genDerivedTypeDestroyWithoutFinalization(*bldr, loc, box);
1855+
});
1856+
}
18471857
return varOp;
18481858
}
18491859

flang/test/Lower/HLFIR/structure-constructor.f90

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ end subroutine test4
161161
! 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>>>>>
162162
! CHECK: }
163163
! 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>>>>}>>
164+
! 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>
165+
! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_27]]
164166
! CHECK: return
165167
! CHECK: }
166168

@@ -201,6 +203,8 @@ end subroutine test5
201203
! 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>>>>}>>>>>
202204
! CHECK: }
203205
! 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>>>>}>>>>}>>
206+
! 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>
207+
! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_24]]
204208
! CHECK: return
205209
! CHECK: }
206210

@@ -291,6 +295,10 @@ end subroutine test6
291295
! 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>}>>
292296
! 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>}>>>
293297
! 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>}>>}>>
298+
! 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>
299+
! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_71]]
300+
! 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>
301+
! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_72]]
294302
! CHECK: return
295303
! CHECK: }
296304

@@ -375,6 +383,8 @@ end subroutine test8
375383
! 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>>>>
376384
! CHECK: }
377385
! 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>>>}>>
386+
! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_15]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
387+
! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_30]]
378388
! CHECK: return
379389
! CHECK: }
380390

@@ -410,6 +420,8 @@ end subroutine test9
410420
! 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>>>>
411421
! 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>>>>
412422
! 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>>>}>>
423+
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
424+
! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_21]]
413425
! CHECK: return
414426
! CHECK: }
415427

0 commit comments

Comments
 (0)