-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[flang] Deallocate INTENT(OUT) dummy allocatable components #69164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Non POINTER/ALLOCATABLE INTENT(OUT) dummy arguments with allocatable components were reset without a proper deallocation if needed. Add a call to Destroy runtime to deallocate the components on entry. Notes: 1. The same logic is not needed on the callee side of BIND(C) call because BIND(C) arguments cannot be derived type with allocatable components (C1806). 2. When the argument is an INTENT(OUT) polymorphic, the dynamic type of the actual may contain allocatable components. This case is covered by the call to Destroy that uses dynamic type and was already inserted for INTENT(OUT) polymorphic dummies.
@llvm/pr-subscribers-flang-fir-hlfir Author: None (jeanPerier) ChangesNon POINTER/ALLOCATABLE INTENT(OUT) dummy arguments with allocatable components were reset without a proper deallocation if needed. Add a call to Destroy runtime to deallocate the components on entry. Notes:
Full diff: https://github.com/llvm/llvm-project/pull/69164.diff 2 Files Affected:
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 46a59b38ae6abde..895ae2451125d63 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -714,7 +714,10 @@ needDummyIntentoutFinalization(const Fortran::lower::pft::Variable &var) {
return true;
// Intent(out) dummies must be finalized at runtime if their type has a
// finalization.
- return hasFinalization(sym);
+ // Allocatable components of INTENT(OUT) dummies must be deallocated (9.7.3.2
+ // p6). Calling finalization runtime for this works even if the components
+ // have no final procedures.
+ return hasFinalization(sym) || hasAllocatableDirectComponent(sym);
}
/// Call default initialization runtime routine to initialize \p var.
@@ -747,6 +750,9 @@ static void finalizeAtRuntime(Fortran::lower::AbstractConverter &converter,
// is deallocated; any allocated allocatable object that is a subobject of an
// actual argument corresponding to an INTENT(OUT) dummy argument is
// deallocated.
+// Note that allocatable components of non-ALLOCATABLE INTENT(OUT) dummy
+// arguments are dealt with needDummyIntentoutFinalization (finalization runtime
+// is called to reach the intended component deallocation effect).
static void deallocateIntentOut(Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var,
Fortran::lower::SymMap &symMap) {
diff --git a/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 b/flang/test/Lower/HLFIR/intentout-allocatable-components.f90
new file mode 100644
index 000000000000000..932fafd322a3e3a
--- /dev/null
+++ b/flang/test/Lower/HLFIR/intentout-allocatable-components.f90
@@ -0,0 +1,32 @@
+! Test that allocatable components of non pointer/non allocatable INTENT(OUT)
+! dummy arguments are deallocated.
+! RUN: bbc -emit-hlfir -polymorphic-type %s -o - -I nowhere | FileCheck %s
+
+subroutine test_intentout_component_deallocate(a)
+ type :: t
+ integer, allocatable :: x
+ end type
+ type(t), intent(out) :: a
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_intentout_component_deallocate(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFtest_intentout_component_deallocateEa"}
+! CHECK: %[[VAL_2:.*]] = fir.embox %[[VAL_1]]#1 : (!fir.ref<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>
+! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.box<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_4:.*]] = fir.call @_FortranADestroy(%[[VAL_3]]) fastmath<contract> : (!fir.box<none>) -> none
+
+subroutine test_intentout_optional_component_deallocate(a)
+ type :: t
+ integer, allocatable :: x
+ end type
+ type(t), optional, intent(out) :: a
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_intentout_optional_component_deallocate(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_out, optional>, uniq_name = "_QFtest_intentout_optional_component_deallocateEa"}
+! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#1 : (!fir.ref<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> i1
+! CHECK: fir.if %[[VAL_2]] {
+! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_1]]#1 : (!fir.ref<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>
+! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.box<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_5:.*]] = fir.call @_FortranADestroy(%[[VAL_4]]) fastmath<contract> : (!fir.box<none>) -> none
+! CHECK: }
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes the leak I was seeing. Thanks very much!
Non POINTER/ALLOCATABLE INTENT(OUT) dummy arguments with allocatable components were reset without a proper deallocation if needed. Add a call to Destroy runtime to deallocate the components on entry.
Notes: