<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/60840>60840</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[flang] Allocatable local variable not deallocated
</td>
</tr>
<tr>
<th>Labels</th>
<td>
flang:frontend
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
rofirrim
</td>
</tr>
</table>
<pre>
(Maybe this has been reported already but I failed to find any issue related to this using "allocatable" or "deallocate" as the query string. Apologies if this is the case)
```fortran
subroutine sub
implicit none
integer, allocatable :: a(:, :)
allocate(a(10, 20))
end subroutine sub
```
I'd expect this array be deallocated upon leaving the subroutine `sub`, but I don't think flang represents this fact in the FIR and no call to `free` (or similar) appears in the final binary.
```
$ ./bin/bbc t.f90 -o -
func.func @_QPsub() {
%c10 = arith.constant 10 : index
%c20 = arith.constant 20 : index
%c1 = arith.constant 1 : index
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?x?xi32>>> {bindc_name = "a", uniq_name = "_QFsubEa"}
%1 = fir.alloca !fir.heap<!fir.array<?x?xi32>> {uniq_name = "_QFsubEa.addr"}
%2 = fir.alloca index {uniq_name = "_QFsubEa.lb0"}
%3 = fir.alloca index {uniq_name = "_QFsubEa.ext0"}
%4 = fir.alloca index {uniq_name = "_QFsubEa.lb1"}
%5 = fir.alloca index {uniq_name = "_QFsubEa.ext1"}
%6 = fir.zero_bits !fir.heap<!fir.array<?x?xi32>>
fir.store %6 to %1 : !fir.ref<!fir.heap<!fir.array<?x?xi32>>>
%7 = fir.allocmem !fir.array<?x?xi32>, %c10, %c20 {fir.must_be_heap = true, uniq_name = "_QFsubEa.alloc"}
fir.store %7 to %1 : !fir.ref<!fir.heap<!fir.array<?x?xi32>>>
fir.store %c10 to %3 : !fir.ref<index>
fir.store %c20 to %5 : !fir.ref<index>
fir.store %c1 to %2 : !fir.ref<index>
fir.store %c1 to %4 : !fir.ref<index>
return
}
...
```
```
; ModuleID = 'FIRModule'
source_filename = "FIRModule"
target triple = "x86_64-unknown-linux-gnu"
declare ptr @malloc(i64)
declare void @free(ptr)
define void @_QPsub() {
%1 = alloca { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }, i64 1, align 8
%2 = alloca ptr, i64 1, align 8
%3 = alloca i64, i64 1, align 8
%4 = alloca i64, i64 1, align 8
%5 = alloca i64, i64 1, align 8
%6 = alloca i64, i64 1, align 8
store ptr null, ptr %2, align 8, !tbaa !1
%7 = call ptr @malloc(i64 mul (i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i64 200))
store ptr %7, ptr %2, align 8, !tbaa !1
store i64 10, ptr %4, align 4, !tbaa !1
store i64 20, ptr %6, align 4, !tbaa !1
store i64 1, ptr %3, align 4, !tbaa !1
store i64 1, ptr %5, align 4, !tbaa !1
ret void
}
!llvm.module.flags = !{!0}
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{!2, !2, i64 0}
!2 = !{!"any data access", !3, i64 0}
!3 = !{!"any access", !4, i64 0}
!4 = !{!"Flang Type TBAA Root"}
```
I expect the code to deallocate the array based on 9.7.3.2p2 of the Fortran 2018 (draft):
> When the execution of a procedure is terminated by execution of a RETURN or END statement, an unsaved
> allocatable local variable of the procedure retains its allocation and definition status if it is a function result or a
> subobject thereof; otherwise, if it is allocated it will be deallocated.
I understand the variable is unsaved (this is a `subroutine`, not a `program`) and it is not a function result or a subobject of the result, so it should be deallocated. I might be misinterpreting the spec though.
On the other hand, I found HLFIR will include a `hlfir.deallocate` operation, so maybe the plan is to implement the required behaviour on top of HLFIR?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0WFtv67gR_jX0yyCCRMm3Bz84x8eoge62G5y2jwEljWx2KVKHlxy7v74YSo7l2Dm7CbBAIovUN9_McIaXoXBO7jXiik0f2XQzEcEfjF1Z00hrZTspTX1aMb74RZxKBH-QDg7CQYmowWJnrMcahLIo6hOUwcMOGiEV1uANNFLXIPQJpHMBwaISvv8SiYKTeg-Mc6GUqYQXpULGORhLnTUO3bFPOPAHhO8B7Qmct1LvE1h3Rpm9RAey6SllD6uEQ8aXLN2wdD08Z2n_1xjrrdB9rwulNcFLjeBC2fcByLZTspIetNE4dErtcY-W8S8wMhdYvmb5GgTjC3rlX2LPtWqAiycLQmYpAXlKuDMUdQ33rHm1e8y4Y3xeAx47rHzvuLBWnKBEuAxbDaEzGhSKFxpnGpeRAjZLSccsmtIHrjaa8Xkk1L9Do4TeU4wtOtTe9XoaUXmQOrJtd08gdA3aQCWUorjS-FpENkuB8YWx4GQrlbCML0F0HQrrztKN1EJBKbWwp-RupIYmLyBhfFtKTc-yAp80yxQeDDz0iCboKqEHsCJ9_u2f5BdfkEo2fxxCwPi0ylJg-QaElf6QVEY7L7SH2EvxrfF4jheh-V00v0VH6rvMd4l72kbapA8UMJ5RqzRHln8ZGgcU3aUVg0vNfHukf5lzln_t_8jHUuq6etaixchNM4pxToENWn6_-vD829aF8mv8Pt-MzMreMetPWkJmvKssEXVtbzTytxrjSP2cSJXpDU_-CR48-lui4lMGZTc8088ZdEs0eyX6H1rzXErvPhiWgYwwzhuLPStN1D7i6zOfxeYz2Tcydn7tdYst_JyA1so4K89vNLfmjyTRBuefS3wmQyKttwF_ms-90usRvPJ6_hd4faWAlpdeRX6rol8E3pPkZ8npRyWzQZB_VrD4Q0GLPthhu3wd3CRJ7i_Wb5r5I_xi6qBwtxkiNt_unvouxufDJmyCrfC5kQrHoR0BeQ_0wu7Rg7eyU6-w42L2PCsegv5dmx_6QUkdjg97HV6laqyUsAidt7RBtEOmLOSseLNRn5EvRtYEjVsZX3Te3gAb2kPPuHf2nMuyel5S548Qyb5AVP4FKKvoZ3H_yaaPHI70k8Mxykw3bLoBikNPAll_IpF7DYubxXXQe9H5Hjwfw8-2vQ8vPgaffgw--wC8z2gKrQ5KESCGmU_5GBwXmMyXIm5r2c2qFY8vd_ID2qBgeO289UZqD31GwB49KmxR-17jYojl2BaZc7J6SZNtSLfBF55enf7GjpBVH3SkF45jlI5Ei4to8ceifCw6-5BoNpLMPy05_ROSFn2cdm_Wo_NRMVPqpU3auGwkjRJ7NywTGU1LnqW3EukIQfHig2rG-QbLsIedbgz8G62TdD7m57jmFyqeZddqzhz8HO50DObXYDqu6RPUwgsQVYXODVoYz_K7BPldgreyxV3Z4kZ2Gw_6304dwrfH9RqejPHjjfTNmr671B0IlamRkvtSdcTuoRoRDmswGpbJPMkT3nEwTV859DUY8DRb0NSprWg8TYZ8fRWd_Cv854B9vYBHrIKXRhOJgM6aCutAaeTAo22ljjVPeXqLfPr67V9Pv1JV-fXXDTgvfJy1Mdk0BO3EC9YXhePqjt4UvAgrY3Ow_qLaohdSO6CD2SBHaqkoiluEjE1SGWKNKj1ZK4CKlfjJogvKk23iYoELpSn_OwyxRdPQNmro_Yd08Rh0oXqt9aSHH1KpNyXgVWG1g6BrtFSc1NGRV8eoGO_HgaJxrqTFUCQOJeNQK2rj-y-dNXsr2ti9jD73NvWAey6OPBuGsv9ItM6QuDuYoOq3TsAOWrk_eOpvpaNS3HYW_WtZ22EF_mDC_nDl8D_6zIlDBweha1K0g8YEXcPf_k71axwzqSsVauzdOig6Co1uH2YpmA5tDO1gaTvchiB0SuiYgSbeGsTMGjz7HqSlhMSDeJEmWJoJ3nTketTN8u2kXuX1Ml-KCa6y2Xw2K_h0WkwOq3JWzKt5mi-aKptOl_WyKrM5FlPe5DXP0mIiVzzlecqzeVakPC-SdL7EerFo5ikWGZ81rEixFVIlcUU0dj-JlzCrWboo0okSJSoXL304j5U-y9eNNdojjRJn083Erkj0oQx7x4pUSefdhcxLr-KlUS883cD6_XlDGTGK5yRYtTp437l4V7JlfLuX_hDKpDIt41tSMvw8dNZQvjC-jeY7xrfRg_8HAAD__1RXdG4">