Skip to content

Commit dffd93b

Browse files
authored
[flang][runtime] Fix SAME_TYPE_AS()/EXTENDS_TYPE_OF() for CLASS(*) (#67727)
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.
1 parent 4b8f23e commit dffd93b

File tree

6 files changed

+74
-90
lines changed

6 files changed

+74
-90
lines changed

flang/include/flang/Runtime/descriptor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,8 @@ class Descriptor {
413413
const SubscriptValue *upper = nullptr,
414414
const SubscriptValue *stride = nullptr);
415415

416+
RT_API_ATTRS void ApplyMold(const Descriptor &, int rank);
417+
416418
RT_API_ATTRS void Check() const;
417419

418420
void Dump(FILE * = stdout) const;

flang/runtime/allocatable.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,7 @@ void RTNAME(AllocatableApplyMold)(
130130
// 9.7.1.3 Return so the error can be emitted by AllocatableAllocate.
131131
return;
132132
}
133-
descriptor = mold;
134-
descriptor.set_base_addr(nullptr);
135-
descriptor.raw().attribute = CFI_attribute_allocatable;
136-
descriptor.raw().rank = rank;
137-
if (auto *descAddendum{descriptor.Addendum()}) {
138-
if (const auto *moldAddendum{mold.Addendum()}) {
139-
if (const auto *derived{moldAddendum->derivedType()}) {
140-
descAddendum->set_derivedType(derived);
141-
}
142-
}
143-
}
133+
descriptor.ApplyMold(mold, rank);
144134
}
145135

146136
int RTNAME(AllocatableAllocate)(Descriptor &descriptor, bool hasStat,
@@ -198,14 +188,15 @@ int RTNAME(AllocatableDeallocatePolymorphic)(Descriptor &descriptor,
198188
int stat{RTNAME(AllocatableDeallocate)(
199189
descriptor, hasStat, errMsg, sourceFile, sourceLine)};
200190
if (stat == StatOk) {
201-
DescriptorAddendum *addendum{descriptor.Addendum()};
202-
if (addendum) {
191+
if (DescriptorAddendum * addendum{descriptor.Addendum()}) {
203192
addendum->set_derivedType(derivedType);
193+
descriptor.raw().type = derivedType ? CFI_type_struct : CFI_type_other;
204194
} else {
205195
// Unlimited polymorphic descriptors initialized with
206196
// AllocatableInitIntrinsic do not have an addendum. Make sure the
207197
// derivedType is null in that case.
208198
INTERNAL_CHECK(!derivedType);
199+
descriptor.raw().type = CFI_type_other;
209200
}
210201
}
211202
return stat;

flang/runtime/derived-api.cpp

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -101,73 +101,55 @@ static const typeInfo::DerivedType *GetDerivedType(const Descriptor &desc) {
101101
}
102102

103103
bool RTNAME(SameTypeAs)(const Descriptor &a, const Descriptor &b) {
104-
// Unlimited polymorphic with intrinsic dynamic type.
105-
if (a.raw().type != CFI_type_struct && a.raw().type != CFI_type_other &&
106-
b.raw().type != CFI_type_struct && b.raw().type != CFI_type_other)
107-
return a.raw().type == b.raw().type;
108-
109-
const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
110-
const typeInfo::DerivedType *derivedTypeB{GetDerivedType(b)};
111-
112-
// No dynamic type in one or both descriptor.
113-
if (derivedTypeA == nullptr || derivedTypeB == nullptr) {
114-
return false;
115-
}
116-
117-
// Exact match of derived type.
118-
if (derivedTypeA == derivedTypeB) {
119-
return true;
104+
auto aType{a.raw().type};
105+
auto bType{b.raw().type};
106+
if ((aType != CFI_type_struct && aType != CFI_type_other) ||
107+
(bType != CFI_type_struct && bType != CFI_type_other)) {
108+
// If either type is intrinsic, they must match.
109+
return aType == bType;
110+
} else {
111+
const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
112+
const typeInfo::DerivedType *derivedTypeB{GetDerivedType(b)};
113+
if (derivedTypeA == nullptr || derivedTypeB == nullptr) {
114+
// Unallocated/disassociated CLASS(*) never matches.
115+
return false;
116+
} else if (derivedTypeA == derivedTypeB) {
117+
// Exact match of derived type.
118+
return true;
119+
} else {
120+
// Otherwise compare with the name. Note 16.29 kind type parameters are
121+
// not considered in the test.
122+
return CompareDerivedTypeNames(
123+
derivedTypeA->name(), derivedTypeB->name());
124+
}
120125
}
121-
// Otherwise compare with the name. Note 16.29 kind type parameters are not
122-
// considered in the test.
123-
return CompareDerivedTypeNames(derivedTypeA->name(), derivedTypeB->name());
124126
}
125127

126128
bool RTNAME(ExtendsTypeOf)(const Descriptor &a, const Descriptor &mold) {
127-
if (a.raw().type != CFI_type_struct && a.raw().type != CFI_type_other &&
128-
mold.raw().type != CFI_type_struct && mold.raw().type != CFI_type_other)
129-
return a.raw().type == mold.raw().type;
130-
131-
const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
132-
const typeInfo::DerivedType *derivedTypeMold{GetDerivedType(mold)};
133-
134-
// If MOLD is unlimited polymorphic and is either a disassociated pointer or
135-
// unallocated allocatable, the result is true.
136-
// Unlimited polymorphic descriptors are initialized with a CFI_type_other
137-
// type.
138-
if (mold.type().raw() == CFI_type_other &&
139-
(mold.IsAllocatable() || mold.IsPointer()) &&
140-
derivedTypeMold == nullptr) {
141-
return true;
142-
}
143-
144-
// If A is unlimited polymorphic and is either a disassociated pointer or
145-
// unallocated allocatable, the result is false.
146-
// Unlimited polymorphic descriptors are initialized with a CFI_type_other
147-
// type.
148-
if (a.type().raw() == CFI_type_other &&
149-
(a.IsAllocatable() || a.IsPointer()) && derivedTypeA == nullptr) {
150-
return false;
151-
}
152-
153-
if (derivedTypeA == nullptr || derivedTypeMold == nullptr) {
129+
auto aType{a.raw().type};
130+
auto moldType{mold.raw().type};
131+
if ((aType != CFI_type_struct && aType != CFI_type_other) ||
132+
(moldType != CFI_type_struct && moldType != CFI_type_other)) {
133+
// If either type is intrinsic, they must match.
134+
return aType == moldType;
135+
} else if (const typeInfo::DerivedType *
136+
derivedTypeMold{GetDerivedType(mold)}) {
137+
// If A is unlimited polymorphic and is either a disassociated pointer or
138+
// unallocated allocatable, the result is false.
139+
// Otherwise if the dynamic type of A or MOLD is extensible, the result is
140+
// true if and only if the dynamic type of A is an extension type of the
141+
// dynamic type of MOLD.
142+
for (const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
143+
derivedTypeA; derivedTypeA = derivedTypeA->GetParentType()) {
144+
if (CompareDerivedType(derivedTypeA, derivedTypeMold)) {
145+
return true;
146+
}
147+
}
154148
return false;
155-
}
156-
157-
// Otherwise if the dynamic type of A or MOLD is extensible, the result is
158-
// true if and only if the dynamic type of A is an extension type of the
159-
// dynamic type of MOLD.
160-
if (CompareDerivedType(derivedTypeA, derivedTypeMold)) {
149+
} else {
150+
// MOLD is unlimited polymorphic and unallocated/disassociated.
161151
return true;
162152
}
163-
const typeInfo::DerivedType *parent{derivedTypeA->GetParentType()};
164-
while (parent) {
165-
if (CompareDerivedType(parent, derivedTypeMold)) {
166-
return true;
167-
}
168-
parent = parent->GetParentType();
169-
}
170-
return false;
171153
}
172154

173155
void RTNAME(DestroyWithoutFinalization)(const Descriptor &descriptor) {

flang/runtime/descriptor.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,22 @@ RT_API_ATTRS bool Descriptor::EstablishPointerSection(const Descriptor &source,
243243
return CFI_section(&raw_, &source.raw_, lower, upper, stride) == CFI_SUCCESS;
244244
}
245245

246+
RT_API_ATTRS void Descriptor::ApplyMold(const Descriptor &mold, int rank) {
247+
raw_.elem_len = mold.raw_.elem_len;
248+
raw_.rank = rank;
249+
raw_.type = mold.raw_.type;
250+
for (int j{0}; j < rank && j < mold.raw_.rank; ++j) {
251+
GetDimension(j) = mold.GetDimension(j);
252+
}
253+
if (auto *addendum{Addendum()}) {
254+
if (auto *moldAddendum{mold.Addendum()}) {
255+
*addendum = *moldAddendum;
256+
} else {
257+
INTERNAL_CHECK(!addendum->derivedType());
258+
}
259+
}
260+
}
261+
246262
RT_API_ATTRS void Descriptor::Check() const {
247263
// TODO
248264
}

flang/runtime/pointer.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,7 @@ void RTNAME(PointerSetDerivedLength)(
5656

5757
void RTNAME(PointerApplyMold)(
5858
Descriptor &pointer, const Descriptor &mold, int rank) {
59-
pointer = mold;
60-
pointer.set_base_addr(nullptr);
61-
pointer.raw().attribute = CFI_attribute_pointer;
62-
pointer.raw().rank = rank;
63-
if (auto *pointerAddendum{pointer.Addendum()}) {
64-
if (const auto *moldAddendum{mold.Addendum()}) {
65-
if (const auto *derived{moldAddendum->derivedType()}) {
66-
pointerAddendum->set_derivedType(derived);
67-
}
68-
}
69-
}
59+
pointer.ApplyMold(mold, rank);
7060
}
7161

7262
void RTNAME(PointerAssociateScalar)(Descriptor &pointer, void *target) {
@@ -183,14 +173,15 @@ int RTNAME(PointerDeallocatePolymorphic)(Descriptor &pointer,
183173
int stat{RTNAME(PointerDeallocate)(
184174
pointer, hasStat, errMsg, sourceFile, sourceLine)};
185175
if (stat == StatOk) {
186-
DescriptorAddendum *addendum{pointer.Addendum()};
187-
if (addendum) {
176+
if (DescriptorAddendum * addendum{pointer.Addendum()}) {
188177
addendum->set_derivedType(derivedType);
178+
pointer.raw().type = derivedType ? CFI_type_struct : CFI_type_other;
189179
} else {
190180
// Unlimited polymorphic descriptors initialized with
191181
// PointerNullifyIntrinsic do not have an addendum. Make sure the
192182
// derivedType is null in that case.
193183
INTERNAL_CHECK(!derivedType);
184+
pointer.raw().type = CFI_type_other;
194185
}
195186
}
196187
return stat;

flang/runtime/type-info.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,12 @@ FILE *DerivedType::Dump(FILE *f) const {
251251
std::fprintf(
252252
f, "\n special descriptor (byteSize 0x%zx): ", special_.byteSize);
253253
specialDesc.Dump(f);
254-
std::size_t specials{specialDesc.Elements()};
255-
for (std::size_t j{0}; j < specials; ++j) {
256-
std::fprintf(f, " [%3zd] ", j);
257-
specialDesc.ZeroBasedIndexedElement<SpecialBinding>(j)->Dump(f);
254+
if (specialDesc.IsAllocated()) {
255+
std::size_t specials{specialDesc.Elements()};
256+
for (std::size_t j{0}; j < specials; ++j) {
257+
std::fprintf(f, " [%3zd] ", j);
258+
specialDesc.ZeroBasedIndexedElement<SpecialBinding>(j)->Dump(f);
259+
}
258260
}
259261
return f;
260262
}

0 commit comments

Comments
 (0)