Skip to content

Commit 21a406c

Browse files
authored
[flang] Improve runtime SAME_TYPE_AS() (#135670)
The present implementation of the intrinsic function SAME_TYPE_AS() yields false positive .TRUE. results for distinct derived types that happen to have the same name. Replace with an implementation that can now depend on derived type information records being the same type if and only if they are at the same location, or are PDT instantiations of the same uninstantiated derived type. And ensure that the derived type information includes references from instantiated PDTs to their original types. (The derived type information format supports these references already, but they were not being set, perhaps because the current faulty SAME_TYPE_AS implementation didn't need them, and nothing else does.) Fixes #135580.
1 parent 34f3466 commit 21a406c

File tree

4 files changed

+35
-47
lines changed

4 files changed

+35
-47
lines changed

flang-rt/include/flang-rt/runtime/type-info.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,13 @@ class DerivedType {
210210
}
211211
RT_API_ATTRS const Descriptor &name() const { return name_.descriptor(); }
212212
RT_API_ATTRS std::uint64_t sizeInBytes() const { return sizeInBytes_; }
213-
RT_API_ATTRS const Descriptor &uninstatiated() const {
213+
RT_API_ATTRS const Descriptor &uninstantiated() const {
214214
return uninstantiated_.descriptor();
215215
}
216+
RT_API_ATTRS const DerivedType *uninstantiatedType() const {
217+
return reinterpret_cast<const DerivedType *>(
218+
uninstantiated().raw().base_addr);
219+
}
216220
RT_API_ATTRS const Descriptor &kindParameter() const {
217221
return kindParameter_.descriptor();
218222
}

flang-rt/lib/runtime/derived-api.cpp

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -83,27 +83,6 @@ bool RTDEF(ClassIs)(
8383
return false;
8484
}
8585

86-
static RT_API_ATTRS bool CompareDerivedTypeNames(
87-
const Descriptor &a, const Descriptor &b) {
88-
if (a.raw().version == CFI_VERSION &&
89-
a.type() == TypeCode{TypeCategory::Character, 1} &&
90-
a.ElementBytes() > 0 && a.rank() == 0 && a.OffsetElement() != nullptr &&
91-
a.raw().version == CFI_VERSION &&
92-
b.type() == TypeCode{TypeCategory::Character, 1} &&
93-
b.ElementBytes() > 0 && b.rank() == 0 && b.OffsetElement() != nullptr &&
94-
a.ElementBytes() == b.ElementBytes() &&
95-
Fortran::runtime::memcmp(
96-
a.OffsetElement(), b.OffsetElement(), a.ElementBytes()) == 0) {
97-
return true;
98-
}
99-
return false;
100-
}
101-
102-
inline RT_API_ATTRS bool CompareDerivedType(
103-
const typeInfo::DerivedType *a, const typeInfo::DerivedType *b) {
104-
return a == b || CompareDerivedTypeNames(a->name(), b->name());
105-
}
106-
10786
static RT_API_ATTRS const typeInfo::DerivedType *GetDerivedType(
10887
const Descriptor &desc) {
10988
if (const DescriptorAddendum * addendum{desc.Addendum()}) {
@@ -121,22 +100,21 @@ bool RTDEF(SameTypeAs)(const Descriptor &a, const Descriptor &b) {
121100
(bType != CFI_type_struct && bType != CFI_type_other)) {
122101
// If either type is intrinsic, they must match.
123102
return aType == bType;
124-
} else {
125-
const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
126-
const typeInfo::DerivedType *derivedTypeB{GetDerivedType(b)};
127-
if (derivedTypeA == nullptr || derivedTypeB == nullptr) {
128-
// Unallocated/disassociated CLASS(*) never matches.
129-
return false;
130-
} else if (derivedTypeA == derivedTypeB) {
131-
// Exact match of derived type.
132-
return true;
133-
} else {
134-
// Otherwise compare with the name. Note 16.29 kind type parameters are
135-
// not considered in the test.
136-
return CompareDerivedTypeNames(
137-
derivedTypeA->name(), derivedTypeB->name());
103+
} else if (const typeInfo::DerivedType * derivedTypeA{GetDerivedType(a)}) {
104+
if (const typeInfo::DerivedType * derivedTypeB{GetDerivedType(b)}) {
105+
if (derivedTypeA == derivedTypeB) {
106+
return true;
107+
} else if (const typeInfo::DerivedType *
108+
uninstDerivedTypeA{derivedTypeA->uninstantiatedType()}) {
109+
// There are KIND type parameters, are these the same type if those
110+
// are ignored?
111+
const typeInfo::DerivedType *uninstDerivedTypeB{
112+
derivedTypeB->uninstantiatedType()};
113+
return uninstDerivedTypeA == uninstDerivedTypeB;
114+
}
138115
}
139116
}
117+
return false;
140118
}
141119

142120
bool RTDEF(ExtendsTypeOf)(const Descriptor &a, const Descriptor &mold) {
@@ -155,7 +133,7 @@ bool RTDEF(ExtendsTypeOf)(const Descriptor &a, const Descriptor &mold) {
155133
// dynamic type of MOLD.
156134
for (const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
157135
derivedTypeA; derivedTypeA = derivedTypeA->GetParentType()) {
158-
if (CompareDerivedType(derivedTypeA, derivedTypeMold)) {
136+
if (derivedTypeA == derivedTypeMold) {
159137
return true;
160138
}
161139
}

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class RuntimeTableBuilder {
5858
void DescribeTypes(Scope &scope, bool inSchemata);
5959

6060
private:
61-
const Symbol *DescribeType(Scope &);
61+
const Symbol *DescribeType(Scope &, bool wantUninstantiatedPDT);
6262
const Symbol &GetSchemaSymbol(const char *) const;
6363
const DeclTypeSpec &GetSchema(const char *) const;
6464
SomeExpr GetEnumValue(const char *) const;
@@ -238,7 +238,7 @@ void RuntimeTableBuilder::DescribeTypes(Scope &scope, bool inSchemata) {
238238
inSchemata |= ignoreScopes_.find(&scope) != ignoreScopes_.end();
239239
if (scope.IsDerivedType()) {
240240
if (!inSchemata) { // don't loop trying to describe a schema
241-
DescribeType(scope);
241+
DescribeType(scope, /*wantUninstantiatedPDT=*/false);
242242
}
243243
} else {
244244
scope.InstantiateDerivedTypes();
@@ -310,10 +310,10 @@ static SomeExpr StructureExpr(evaluate::StructureConstructor &&x) {
310310
return SomeExpr{evaluate::Expr<evaluate::SomeDerived>{std::move(x)}};
311311
}
312312

313-
static int GetIntegerKind(const Symbol &symbol) {
313+
static int GetIntegerKind(const Symbol &symbol, bool canBeUninstantiated) {
314314
auto dyType{evaluate::DynamicType::From(symbol)};
315315
CHECK((dyType && dyType->category() == TypeCategory::Integer) ||
316-
symbol.owner().context().HasError(symbol));
316+
symbol.owner().context().HasError(symbol) || canBeUninstantiated);
317317
return dyType && dyType->category() == TypeCategory::Integer
318318
? dyType->kind()
319319
: symbol.owner().context().GetDefaultKind(TypeCategory::Integer);
@@ -395,7 +395,8 @@ static std::optional<std::string> GetSuffixIfTypeKindParameters(
395395
return std::nullopt;
396396
}
397397

398-
const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
398+
const Symbol *RuntimeTableBuilder::DescribeType(
399+
Scope &dtScope, bool wantUninstantiatedPDT) {
399400
if (const Symbol * info{dtScope.runtimeDerivedTypeDescription()}) {
400401
return info;
401402
}
@@ -449,7 +450,7 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
449450
GetSuffixIfTypeKindParameters(*derivedTypeSpec, parameters)}) {
450451
distinctName += *suffix;
451452
}
452-
} else if (isPDTDefinitionWithKindParameters) {
453+
} else if (isPDTDefinitionWithKindParameters && !wantUninstantiatedPDT) {
453454
return nullptr;
454455
}
455456
std::string dtDescName{(fir::kTypeDescriptorSeparator + distinctName).str()};
@@ -480,7 +481,8 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
480481
}
481482
if (const Symbol *
482483
uninstDescObject{isPDTInstantiation
483-
? DescribeType(DEREF(const_cast<Scope *>(dtSymbol->scope())))
484+
? DescribeType(DEREF(const_cast<Scope *>(dtSymbol->scope())),
485+
/*wantUninstantiatedPDT=*/true)
484486
: nullptr}) {
485487
AddValue(dtValues, derivedTypeSchema_, "uninstantiated"s,
486488
evaluate::AsGenericExpr(evaluate::Expr<evaluate::SomeDerived>{
@@ -516,7 +518,8 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
516518
}
517519
kinds.emplace_back(value);
518520
} else { // LEN= parameter
519-
lenKinds.emplace_back(GetIntegerKind(*inst));
521+
lenKinds.emplace_back(
522+
GetIntegerKind(*inst, isPDTDefinitionWithKindParameters));
520523
}
521524
}
522525
}
@@ -804,7 +807,9 @@ evaluate::StructureConstructor RuntimeTableBuilder::DescribeComponent(
804807
const DerivedTypeSpec &spec{dyType.GetDerivedTypeSpec()};
805808
Scope *derivedScope{const_cast<Scope *>(
806809
spec.scope() ? spec.scope() : spec.typeSymbol().scope())};
807-
if (const Symbol * derivedDescription{DescribeType(DEREF(derivedScope))}) {
810+
if (const Symbol *
811+
derivedDescription{DescribeType(
812+
DEREF(derivedScope), /*wantUninstantiatedPDT=*/false)}) {
808813
AddValue(values, componentSchema_, "derived"s,
809814
evaluate::AsGenericExpr(evaluate::Expr<evaluate::SomeDerived>{
810815
evaluate::Designator<evaluate::SomeDerived>{

flang/test/Semantics/typeinfo01.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ module m03
3434
end type
3535
type(kpdt(4)) :: x
3636
!CHECK: .c.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.a,genre=1_1,category=2_1,kind=4_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
37-
!CHECK: .dt.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.kpdt,sizeinbytes=4_8,uninstantiated=NULL(),kindparameter=.kp.kpdt.4,lenparameterkind=NULL(),component=.c.kpdt.4,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1)
37+
!CHECK: .dt.kpdt, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(name=.n.kpdt,uninstantiated=NULL(),kindparameter=.kp.kpdt,lenparameterkind=NULL())
38+
!CHECK: .dt.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.kpdt,sizeinbytes=4_8,uninstantiated=.dt.kpdt,kindparameter=.kp.kpdt.4,lenparameterkind=NULL(),component=.c.kpdt.4,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1)
3839
!CHECK: .kp.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: INTEGER(8) shape: 0_8:0_8 init:[INTEGER(8)::4_8]
3940
end module
4041

0 commit comments

Comments
 (0)