Skip to content

[flang] Fix searches for polymorphic components #102212

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

Merged
merged 1 commit into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions flang/include/flang/Semantics/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,18 @@ std::list<std::list<SymbolRef>> GetStorageAssociations(const Scope &);
// closure of its components (including POINTERs) and the
// PotentialAndPointer subobject components of its non-POINTER derived type
// components.
//
// type t1 ultimate components: x, a, p
// real x direct components: x, a, p
// real, allocatable :: a potential components: x, a
// real, pointer :: p potential & pointers: x, a, p
// end type
// type t2 ultimate components: y, c%x, c%a, c%p, b
// real y direct components: y, c, c%x, c%a, c%p, b
// type(t1) :: c potential components: y, c, c%x, c%a, b, b%x, b%a
// type(t1), allocatable :: b potential & pointers: potentials + c%p + b%p
// end type
//
// Parent and procedure components are considered against these definitions.
// For this kind of iterator, the component tree is recursively visited in the
// following order:
Expand Down Expand Up @@ -620,8 +632,8 @@ UltimateComponentIterator::const_iterator FindAllocatableUltimateComponent(
const DerivedTypeSpec &);
DirectComponentIterator::const_iterator FindAllocatableOrPointerDirectComponent(
const DerivedTypeSpec &);
UltimateComponentIterator::const_iterator
FindPolymorphicAllocatableUltimateComponent(const DerivedTypeSpec &);
PotentialComponentIterator::const_iterator
FindPolymorphicAllocatablePotentialComponent(const DerivedTypeSpec &);

// The LabelEnforce class (given a set of labels) provides an error message if
// there is a branch to a label which is not in the given set.
Expand Down
5 changes: 3 additions & 2 deletions flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,10 @@ void CheckHelper::Check(const Symbol &symbol) {
messages_.Say(
"Result of pure function may not have an impure FINAL subroutine"_err_en_US);
}
if (auto bad{FindPolymorphicAllocatableUltimateComponent(*derived)}) {
if (auto bad{
FindPolymorphicAllocatablePotentialComponent(*derived)}) {
SayWithDeclaration(*bad,
"Result of pure function may not have polymorphic ALLOCATABLE ultimate component '%s'"_err_en_US,
"Result of pure function may not have polymorphic ALLOCATABLE potential component '%s'"_err_en_US,
bad.BuildResultDesignatorName());
}
}
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Semantics/definable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ static std::optional<parser::Message> WhyNotDefinableLast(parser::CharBlock at,
}
if (const DerivedTypeSpec * derived{GetDerivedTypeSpec(dyType)}) {
if (!flags.test(DefinabilityFlag::PolymorphicOkInPure)) {
if (auto bad{FindPolymorphicAllocatableUltimateComponent(*derived)}) {
if (auto bad{
FindPolymorphicAllocatablePotentialComponent(*derived)}) {
return BlameSymbol(at,
"'%s' has polymorphic component '%s' in a pure subprogram"_en_US,
original, bad.BuildResultDesignatorName());
Expand Down
10 changes: 5 additions & 5 deletions flang/lib/Semantics/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ const Symbol *HasImpureFinal(const Symbol &original, std::optional<int> rank) {

bool MayRequireFinalization(const DerivedTypeSpec &derived) {
return IsFinalizable(derived) ||
FindPolymorphicAllocatableUltimateComponent(derived);
FindPolymorphicAllocatablePotentialComponent(derived);
}

bool HasAllocatableDirectComponent(const DerivedTypeSpec &derived) {
Expand Down Expand Up @@ -1404,11 +1404,11 @@ DirectComponentIterator::const_iterator FindAllocatableOrPointerDirectComponent(
return std::find_if(directs.begin(), directs.end(), IsAllocatableOrPointer);
}

UltimateComponentIterator::const_iterator
FindPolymorphicAllocatableUltimateComponent(const DerivedTypeSpec &derived) {
UltimateComponentIterator ultimates{derived};
PotentialComponentIterator::const_iterator
FindPolymorphicAllocatablePotentialComponent(const DerivedTypeSpec &derived) {
PotentialComponentIterator potentials{derived};
return std::find_if(
ultimates.begin(), ultimates.end(), IsPolymorphicAllocatable);
potentials.begin(), potentials.end(), IsPolymorphicAllocatable);
}

const Symbol *FindUltimateComponent(const DerivedTypeSpec &derived,
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Semantics/call10.f90
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pure function f07() ! C1585
class(t), allocatable :: f07
end function
pure function f08() ! C1585
!ERROR: Result of pure function may not have polymorphic ALLOCATABLE ultimate component '%a'
!ERROR: Result of pure function may not have polymorphic ALLOCATABLE potential component '%a'
type(polyAlloc) :: f08
end function

Expand Down
17 changes: 17 additions & 0 deletions flang/test/Semantics/typeinfo11.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
!RUN: bbc --dump-symbols %s | FileCheck %s
!RUN: %flang_fc1 -fdebug-dump-symbols %s | FileCheck %s

!Tests that derived types with polymorphic potential subobject
!components do not have their noFinalizationNeeded flags set, even
!when those components are packaged within another allocatable.

type t1
class(*), allocatable :: a
end type
type t2
type(t1), allocatable :: b
end type
type(t2) x
end

!CHECK: .dt.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t2,sizeinbytes=40_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.t2,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=0_1,nodestructionneeded=0_1,nofinalizationneeded=0_1)
Loading