[flang-commits] [flang] deb2861 - [flang] Allow for equivalent types in non-TBP defined I/O (#158755)
via flang-commits
flang-commits at lists.llvm.org
Wed Sep 17 09:16:01 PDT 2025
Author: Peter Klausler
Date: 2025-09-17T09:15:57-07:00
New Revision: deb2861b07e503b729b854edbffdeae7cd4a1aa6
URL: https://github.com/llvm/llvm-project/commit/deb2861b07e503b729b854edbffdeae7cd4a1aa6
DIFF: https://github.com/llvm/llvm-project/commit/deb2861b07e503b729b854edbffdeae7cd4a1aa6.diff
LOG: [flang] Allow for equivalent types in non-TBP defined I/O (#158755)
Non-extensible derived type -- those with SEQUENCE or BIND(C) -- are
allowed as monomorphic "dtv" dummy arguments to defined I/O subroutines.
Fortran's type rules admit structural equivalence for these types, and
it's possible that I/O might be attempted in a scope using a
non-extensible type that's equivalent to a non-type-bound generic
interface's specific procedure's "dtv" dummy argument's type, but not
defined in the same place.
Fixes https://github.com/llvm/llvm-project/issues/158673.
This is an IBM Fortran test case that doesn't need to be duplicated in
LLVM.
Added:
Modified:
flang/lib/Semantics/runtime-type-info.cpp
Removed:
################################################################################
diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp
index b8c3db8723964..bbaded36c62e3 100644
--- a/flang/lib/Semantics/runtime-type-info.cpp
+++ b/flang/lib/Semantics/runtime-type-info.cpp
@@ -1385,12 +1385,31 @@ CollectNonTbpDefinedIoGenericInterfaces(
if (const DeclTypeSpec *
declType{GetDefinedIoSpecificArgType(*specific)}) {
const DerivedTypeSpec &derived{DEREF(declType->AsDerived())};
- if (const Symbol *
- dtDesc{derived.scope()
- ? derived.scope()->runtimeDerivedTypeDescription()
+ const Scope *derivedScope{derived.scope()};
+ if (!declType->IsPolymorphic()) {
+ // A defined I/O subroutine with a monomorphic "dtv" dummy
+ // argument implies a non-extensible sequence or BIND(C) derived
+ // type. Such types may be defined more than once in the program
+ // so long as they are structurally equivalent. If the current
+ // scope has an equivalent type, use it for the table rather
+ // than the "dtv" argument's type.
+ if (const Symbol *inScope{scope.FindSymbol(derived.name())}) {
+ const Symbol &ultimate{inScope->GetUltimate()};
+ DerivedTypeSpec localDerivedType{inScope->name(), ultimate};
+ if (ultimate.has<DerivedTypeDetails>() &&
+ evaluate::DynamicType{derived, /*isPolymorphic=*/false}
+ .IsTkCompatibleWith(evaluate::DynamicType{
+ localDerivedType, /*iP=*/false})) {
+ derivedScope = ultimate.scope();
+ }
+ }
+ }
+ if (const Symbol *dtDesc{derivedScope
+ ? derivedScope->runtimeDerivedTypeDescription()
: nullptr}) {
if (useRuntimeTypeInfoEntries &&
- &derived.scope()->parent() == &generic->owner()) {
+ derivedScope == derived.scope() &&
+ &derivedScope->parent() == &generic->owner()) {
// This non-TBP defined I/O generic was defined in the
// same scope as the derived type, and it will be
// included in the derived type's special bindings
@@ -1454,7 +1473,8 @@ static const Symbol *FindSpecificDefinedIo(const Scope &scope,
const Symbol &specific{*ref};
if (const DeclTypeSpec *
thisType{GetDefinedIoSpecificArgType(specific)}) {
- if (evaluate::DynamicType{DEREF(thisType->AsDerived()), true}
+ if (evaluate::DynamicType{
+ DEREF(thisType->AsDerived()), thisType->IsPolymorphic()}
.IsTkCompatibleWith(derived)) {
return &specific.GetUltimate();
}
More information about the flang-commits
mailing list