Skip to content

Commit 30dc037

Browse files
committed
[flang] Avoid double cleanup when the result is cleaned up by the Destroy function
The Destroy runtime function does free the memory so do not do it inlined when we use Destroy. This avoid a double free execution error. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D145372
1 parent 1edc723 commit 30dc037

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

flang/lib/Lower/ConvertCall.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult(
415415
// in any cases.
416416
std::optional<Fortran::evaluate::DynamicType> retTy =
417417
caller.getCallDescription().proc().GetType();
418+
bool cleanupWithDestroy = false;
418419
if (!fir::isPointerType(funcType.getResults()[0]) && retTy &&
419420
(retTy->category() == Fortran::common::TypeCategory::Derived ||
420421
retTy->IsPolymorphic() || retTy->IsUnlimitedPolymorphic())) {
@@ -424,6 +425,7 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult(
424425
fir::runtime::genDerivedTypeDestroy(*bldr, loc,
425426
fir::getBase(*allocatedResult));
426427
});
428+
cleanupWithDestroy = true;
427429
} else {
428430
const Fortran::semantics::DerivedTypeSpec &typeSpec =
429431
retTy->GetDerivedTypeSpec();
@@ -433,12 +435,13 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult(
433435
mlir::Value box = bldr->createBox(loc, *allocatedResult);
434436
fir::runtime::genDerivedTypeDestroy(*bldr, loc, box);
435437
});
438+
cleanupWithDestroy = true;
436439
}
437440
}
438441
}
439442
allocatedResult->match(
440443
[&](const fir::MutableBoxValue &box) {
441-
if (box.isAllocatable()) {
444+
if (box.isAllocatable() && !cleanupWithDestroy) {
442445
// 9.7.3.2 point 4. Finalize allocatables.
443446
fir::FirOpBuilder *bldr = &converter.getFirOpBuilder();
444447
stmtCtx.attachCleanup([bldr, loc, box]() {

flang/test/Lower/derived-type-finalization.f90

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module derived_type_finalization
1010
integer :: a
1111
contains
1212
final :: t1_final
13+
final :: t1_final_1r
1314
end type
1415

1516
type :: t2
@@ -28,6 +29,10 @@ subroutine t1_final(this)
2829
type(t1) :: this
2930
end subroutine
3031

32+
subroutine t1_final_1r(this)
33+
type(t1) :: this(:)
34+
end subroutine
35+
3136
subroutine t2_final(this)
3237
type(t2) :: this
3338
end subroutine
@@ -203,6 +208,25 @@ function no_func_ret_finalize() result(ty)
203208
! CHECK: %{{.*}} = fir.call @_FortranADestroy
204209
! CHECK: return %{{.*}} : !fir.type<_QMderived_type_finalizationTt1{a:i32}>
205210

211+
function copy(a) result(ty)
212+
class(t1), allocatable :: ty(:)
213+
integer, intent(in) :: a
214+
allocate(t1::ty(a))
215+
ty%a = 1
216+
end function
217+
218+
subroutine test_avoid_double_free()
219+
class(*), allocatable :: up(:)
220+
allocate(up(10), source=copy(10))
221+
end subroutine
222+
223+
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_avoid_double_free() {
224+
! CHECK: %[[RES:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>> {bindc_name = ".result"}
225+
! CHECK: fir.call @_FortranAAllocatableAllocateSource(
226+
! CHECK-NOT: fir.freemem %{{.*}} : !fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
227+
! CHECK: %[[RES_CONV:.*]] = fir.convert %[[RES]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>>) -> !fir.box<none>
228+
! CHECK: %{{.*}} = fir.call @_FortranADestroy(%[[RES_CONV]]) {{.*}} : (!fir.box<none>) -> none
229+
206230
end module
207231

208232
program p

0 commit comments

Comments
 (0)