Skip to content

Commit 710503f

Browse files
authored
[flang] Finalize polymorphic alloctable component if needed (llvm#67326)
The runtime skips finalization if the runtime type info "nofinalizationneeded" is set, so it should not be set if the derived type has polymorphic allocatable components since they may be allocated to some type extension with a final methods. IsFinalizable cannot be updated since polymorphic allocatable components do not imply a final routine will actually be called (it depends of the dynamic type, which semantics cannot know about), and this would not match the "Finalizable" definition of the standard in 7.5.6.1. Hence, this patch adds a MayRequireFinalization helper. The component visitor change is to avoid crashing in FindPolymorphicAllocatableUltimateComponent in the test test/Driver/dump-all-bad.f90 that tries generating runtime type info even after some semantic error is raised under debug-dump options.
1 parent 8c556b7 commit 710503f

File tree

4 files changed

+35
-2
lines changed

4 files changed

+35
-2
lines changed

flang/include/flang/Semantics/tools.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ const Symbol *IsFinalizable(const DerivedTypeSpec &,
177177
std::set<const DerivedTypeSpec *> * = nullptr,
178178
bool withImpureFinalizer = false, std::optional<int> rank = std::nullopt);
179179
const Symbol *HasImpureFinal(const Symbol &);
180+
// Is this type finalizable or does it contain any polymorphic allocatable
181+
// ultimate components?
182+
bool MayRequireFinalization(const DerivedTypeSpec &derived);
183+
180184
bool IsInBlankCommon(const Symbol &);
181185
inline bool IsAssumedSizeArray(const Symbol &symbol) {
182186
if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {

flang/lib/Semantics/runtime-type-info.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,8 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
642642
IntExpr<1>(derivedTypeSpec && !derivedTypeSpec->HasDestruction()));
643643
// Similarly, a flag to short-circuit finalization when not needed.
644644
AddValue(dtValues, derivedTypeSchema_, "nofinalizationneeded"s,
645-
IntExpr<1>(derivedTypeSpec && !IsFinalizable(*derivedTypeSpec)));
645+
IntExpr<1>(
646+
derivedTypeSpec && !MayRequireFinalization(*derivedTypeSpec)));
646647
}
647648
dtObject.get<ObjectEntityDetails>().set_init(MaybeExpr{
648649
StructureExpr(Structure(derivedTypeSchema_, std::move(dtValues)))});

flang/lib/Semantics/tools.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,11 @@ const Symbol *HasImpureFinal(const Symbol &original) {
836836
return nullptr;
837837
}
838838

839+
bool MayRequireFinalization(const DerivedTypeSpec &derived) {
840+
return IsFinalizable(derived) ||
841+
FindPolymorphicAllocatableUltimateComponent(derived);
842+
}
843+
839844
bool IsAssumedLengthCharacter(const Symbol &symbol) {
840845
if (const DeclTypeSpec * type{symbol.GetType()}) {
841846
return type->category() == DeclTypeSpec::Character &&
@@ -1249,7 +1254,8 @@ static bool StopAtComponentPre(const Symbol &component) {
12491254
} else if constexpr (componentKind == ComponentKind::Ultimate) {
12501255
return component.has<ProcEntityDetails>() ||
12511256
IsAllocatableOrObjectPointer(&component) ||
1252-
(component.get<ObjectEntityDetails>().type() &&
1257+
(component.has<ObjectEntityDetails>() &&
1258+
component.get<ObjectEntityDetails>().type() &&
12531259
component.get<ObjectEntityDetails>().type()->AsIntrinsic());
12541260
} else if constexpr (componentKind == ComponentKind::Potential) {
12551261
return !IsPointer(component);

flang/test/Semantics/typeinfo07.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
! Test "nofinalizationneeded" is set to false for derived type
2+
! containing polymorphic allocatable ultimate components.
3+
!RUN: %flang_fc1 -fdebug-dump-symbols %s | FileCheck %s
4+
5+
type :: t_base
6+
end type
7+
type :: t_container_not_polymorphic
8+
type(t_base), allocatable :: comp
9+
end type
10+
type :: t_container
11+
class(t_base), allocatable :: comp
12+
end type
13+
type, extends(t_container) :: t_container_extension
14+
end type
15+
type :: t_container_wrapper
16+
type(t_container_extension) :: wrapper
17+
end type
18+
end
19+
! CHECK: .dt.t_container, SAVE, TARGET (CompilerCreated, ReadOnly): {{.*}}noinitializationneeded=0_1,nodestructionneeded=0_1,nofinalizationneeded=0_1)
20+
! CHECK: .dt.t_container_extension, SAVE, TARGET (CompilerCreated, ReadOnly): {{.*}}noinitializationneeded=0_1,nodestructionneeded=0_1,nofinalizationneeded=0_1)
21+
! CHECK: .dt.t_container_not_polymorphic, SAVE, TARGET (CompilerCreated, ReadOnly): {{.*}}noinitializationneeded=0_1,nodestructionneeded=0_1,nofinalizationneeded=1_1)
22+
! CHECK: .dt.t_container_wrapper, SAVE, TARGET (CompilerCreated, ReadOnly): {{.*}}noinitializationneeded=0_1,nodestructionneeded=0_1,nofinalizationneeded=0_1)

0 commit comments

Comments
 (0)