[flang-commits] [flang] [flang][runtime] Fix SAME_TYPE_AS()/EXTENDS_TYPE_OF() for CLASS(*) (PR #67727)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Sep 28 15:13:26 PDT 2023
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/67727
>From 29643a71464857b07ba2b83f89f7e9a913e460f1 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Thu, 28 Sep 2023 12:35:30 -0700
Subject: [PATCH] [flang][runtime] Fix SAME_TYPE_AS()/EXTENDS_TYPE_OF() for
CLASS(*)
Ensure that the f18Addendum flag is preserved in AllocatableApplyMold(),
that raw().type is reinitialized in AllocatableDeallocatePolymorphic(),
and that the implementations of SameTypeAs() and ExtendsTypeOf()
handle unallocated unlimited polymorphic arguments correctly.
---
flang/runtime/allocatable.cpp | 15 +++--
flang/runtime/derived-api.cpp | 102 ++++++++++++++--------------------
flang/runtime/pointer.cpp | 15 +++--
3 files changed, 56 insertions(+), 76 deletions(-)
diff --git a/flang/runtime/allocatable.cpp b/flang/runtime/allocatable.cpp
index 4b9e438e8a10995..2c61ab4b4fed853 100644
--- a/flang/runtime/allocatable.cpp
+++ b/flang/runtime/allocatable.cpp
@@ -130,16 +130,14 @@ void RTNAME(AllocatableApplyMold)(
// 9.7.1.3 Return so the error can be emitted by AllocatableAllocate.
return;
}
+ auto *descAddendum{descriptor.Addendum()};
descriptor = mold;
descriptor.set_base_addr(nullptr);
descriptor.raw().attribute = CFI_attribute_allocatable;
descriptor.raw().rank = rank;
- if (auto *descAddendum{descriptor.Addendum()}) {
- if (const auto *moldAddendum{mold.Addendum()}) {
- if (const auto *derived{moldAddendum->derivedType()}) {
- descAddendum->set_derivedType(derived);
- }
- }
+ if (descAddendum && !mold.Addendum()) {
+ descriptor.raw().f18Addendum = true;
+ INTERNAL_CHECK(!descAddendum->derivedType());
}
}
@@ -198,14 +196,15 @@ int RTNAME(AllocatableDeallocatePolymorphic)(Descriptor &descriptor,
int stat{RTNAME(AllocatableDeallocate)(
descriptor, hasStat, errMsg, sourceFile, sourceLine)};
if (stat == StatOk) {
- DescriptorAddendum *addendum{descriptor.Addendum()};
- if (addendum) {
+ if (DescriptorAddendum * addendum{descriptor.Addendum()}) {
addendum->set_derivedType(derivedType);
+ descriptor.raw().type = derivedType ? CFI_type_struct : CFI_type_other;
} else {
// Unlimited polymorphic descriptors initialized with
// AllocatableInitIntrinsic do not have an addendum. Make sure the
// derivedType is null in that case.
INTERNAL_CHECK(!derivedType);
+ descriptor.raw().type = CFI_type_other;
}
}
return stat;
diff --git a/flang/runtime/derived-api.cpp b/flang/runtime/derived-api.cpp
index 66123030f98b57d..39bf0521e73b16b 100644
--- a/flang/runtime/derived-api.cpp
+++ b/flang/runtime/derived-api.cpp
@@ -101,73 +101,55 @@ static const typeInfo::DerivedType *GetDerivedType(const Descriptor &desc) {
}
bool RTNAME(SameTypeAs)(const Descriptor &a, const Descriptor &b) {
- // Unlimited polymorphic with intrinsic dynamic type.
- if (a.raw().type != CFI_type_struct && a.raw().type != CFI_type_other &&
- b.raw().type != CFI_type_struct && b.raw().type != CFI_type_other)
- return a.raw().type == b.raw().type;
-
- const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
- const typeInfo::DerivedType *derivedTypeB{GetDerivedType(b)};
-
- // No dynamic type in one or both descriptor.
- if (derivedTypeA == nullptr || derivedTypeB == nullptr) {
- return false;
- }
-
- // Exact match of derived type.
- if (derivedTypeA == derivedTypeB) {
- return true;
+ auto aType{a.raw().type};
+ auto bType{b.raw().type};
+ if ((aType != CFI_type_struct && aType != CFI_type_other) ||
+ (bType != CFI_type_struct && bType != CFI_type_other)) {
+ // If either type is intrinsic, they must match.
+ return aType == bType;
+ } else {
+ const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
+ const typeInfo::DerivedType *derivedTypeB{GetDerivedType(b)};
+ if (derivedTypeA == nullptr || derivedTypeB == nullptr) {
+ // Unallocated/disassociated CLASS(*) never matches.
+ return false;
+ } else if (derivedTypeA == derivedTypeB) {
+ // Exact match of derived type.
+ return true;
+ } else {
+ // Otherwise compare with the name. Note 16.29 kind type parameters are
+ // not considered in the test.
+ return CompareDerivedTypeNames(
+ derivedTypeA->name(), derivedTypeB->name());
+ }
}
- // Otherwise compare with the name. Note 16.29 kind type parameters are not
- // considered in the test.
- return CompareDerivedTypeNames(derivedTypeA->name(), derivedTypeB->name());
}
bool RTNAME(ExtendsTypeOf)(const Descriptor &a, const Descriptor &mold) {
- if (a.raw().type != CFI_type_struct && a.raw().type != CFI_type_other &&
- mold.raw().type != CFI_type_struct && mold.raw().type != CFI_type_other)
- return a.raw().type == mold.raw().type;
-
- const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
- const typeInfo::DerivedType *derivedTypeMold{GetDerivedType(mold)};
-
- // If MOLD is unlimited polymorphic and is either a disassociated pointer or
- // unallocated allocatable, the result is true.
- // Unlimited polymorphic descriptors are initialized with a CFI_type_other
- // type.
- if (mold.type().raw() == CFI_type_other &&
- (mold.IsAllocatable() || mold.IsPointer()) &&
- derivedTypeMold == nullptr) {
- return true;
- }
-
- // If A is unlimited polymorphic and is either a disassociated pointer or
- // unallocated allocatable, the result is false.
- // Unlimited polymorphic descriptors are initialized with a CFI_type_other
- // type.
- if (a.type().raw() == CFI_type_other &&
- (a.IsAllocatable() || a.IsPointer()) && derivedTypeA == nullptr) {
- return false;
- }
-
- if (derivedTypeA == nullptr || derivedTypeMold == nullptr) {
+ auto aType{a.raw().type};
+ auto moldType{mold.raw().type};
+ if ((aType != CFI_type_struct && aType != CFI_type_other) ||
+ (moldType != CFI_type_struct && moldType != CFI_type_other)) {
+ // If either type is intrinsic, they must match.
+ return aType == moldType;
+ } else if (const typeInfo::DerivedType *
+ derivedTypeMold{GetDerivedType(mold)}) {
+ // If A is unlimited polymorphic and is either a disassociated pointer or
+ // unallocated allocatable, the result is false.
+ // Otherwise if the dynamic type of A or MOLD is extensible, the result is
+ // true if and only if the dynamic type of A is an extension type of the
+ // dynamic type of MOLD.
+ for (const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
+ derivedTypeA; derivedTypeA = derivedTypeA->GetParentType()) {
+ if (CompareDerivedType(derivedTypeA, derivedTypeMold)) {
+ return true;
+ }
+ }
return false;
- }
-
- // Otherwise if the dynamic type of A or MOLD is extensible, the result is
- // true if and only if the dynamic type of A is an extension type of the
- // dynamic type of MOLD.
- if (CompareDerivedType(derivedTypeA, derivedTypeMold)) {
+ } else {
+ // MOLD is unlimited polymorphic and unallocated/disassociated.
return true;
}
- const typeInfo::DerivedType *parent{derivedTypeA->GetParentType()};
- while (parent) {
- if (CompareDerivedType(parent, derivedTypeMold)) {
- return true;
- }
- parent = parent->GetParentType();
- }
- return false;
}
void RTNAME(DestroyWithoutFinalization)(const Descriptor &descriptor) {
diff --git a/flang/runtime/pointer.cpp b/flang/runtime/pointer.cpp
index 0320468ffdc7904..65b8d24d121c241 100644
--- a/flang/runtime/pointer.cpp
+++ b/flang/runtime/pointer.cpp
@@ -56,16 +56,14 @@ void RTNAME(PointerSetDerivedLength)(
void RTNAME(PointerApplyMold)(
Descriptor &pointer, const Descriptor &mold, int rank) {
+ auto *pointerAddendum{pointer.Addendum()};
pointer = mold;
pointer.set_base_addr(nullptr);
pointer.raw().attribute = CFI_attribute_pointer;
pointer.raw().rank = rank;
- if (auto *pointerAddendum{pointer.Addendum()}) {
- if (const auto *moldAddendum{mold.Addendum()}) {
- if (const auto *derived{moldAddendum->derivedType()}) {
- pointerAddendum->set_derivedType(derived);
- }
- }
+ if (pointerAddendum && !mold.Addendum()) {
+ pointer.raw().f18Addendum = true;
+ INTERNAL_CHECK(!pointerAddendum->derivedType());
}
}
@@ -183,14 +181,15 @@ int RTNAME(PointerDeallocatePolymorphic)(Descriptor &pointer,
int stat{RTNAME(PointerDeallocate)(
pointer, hasStat, errMsg, sourceFile, sourceLine)};
if (stat == StatOk) {
- DescriptorAddendum *addendum{pointer.Addendum()};
- if (addendum) {
+ if (DescriptorAddendum * addendum{pointer.Addendum()}) {
addendum->set_derivedType(derivedType);
+ pointer.raw().type = derivedType ? CFI_type_struct : CFI_type_other;
} else {
// Unlimited polymorphic descriptors initialized with
// PointerNullifyIntrinsic do not have an addendum. Make sure the
// derivedType is null in that case.
INTERNAL_CHECK(!derivedType);
+ pointer.raw().type = CFI_type_other;
}
}
return stat;
More information about the flang-commits
mailing list