Skip to content

Conversation

@klausler
Copy link
Contributor

The code that handles non-type-bound defined I/O for sequence types didn't allow for the type to be shadowed in its scope by a homonymous generic procedure interface.

Fixes #173766.

The code that handles non-type-bound defined I/O for sequence
types didn't allow for the type to be shadowed in its scope by
a homonymous generic procedure interface.

Fixes llvm#173766.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:semantics labels Dec 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 28, 2025

@llvm/pr-subscribers-flang-fir-hlfir

Author: Peter Klausler (klausler)

Changes

The code that handles non-type-bound defined I/O for sequence types didn't allow for the type to be shadowed in its scope by a homonymous generic procedure interface.

Fixes #173766.


Full diff: https://github.com/llvm/llvm-project/pull/173783.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/runtime-type-info.cpp (+13-7)
  • (added) flang/test/Lower/bug173766.f90 (+28)
diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp
index bbaded36c62e3..8f92fda65685a 100644
--- a/flang/lib/Semantics/runtime-type-info.cpp
+++ b/flang/lib/Semantics/runtime-type-info.cpp
@@ -1394,13 +1394,19 @@ CollectNonTbpDefinedIoGenericInterfaces(
               // 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();
+                const Symbol *localDerived{&inScope->GetUltimate()};
+                if (const auto *generic{
+                        localDerived->detailsIf<GenericDetails>()}) {
+                  localDerived = generic->derivedType();
+                }
+                if (localDerived && localDerived->has<DerivedTypeDetails>()) {
+                  DerivedTypeSpec localDerivedType{
+                      inScope->name(), *localDerived};
+                  if (evaluate::DynamicType{derived, /*isPolymorphic=*/false}
+                          .IsTkCompatibleWith(evaluate::DynamicType{
+                              localDerivedType, /*iP=*/false})) {
+                    derivedScope = localDerived->scope();
+                  }
                 }
               }
             }
diff --git a/flang/test/Lower/bug173766.f90 b/flang/test/Lower/bug173766.f90
new file mode 100644
index 0000000000000..a9705f144c563
--- /dev/null
+++ b/flang/test/Lower/bug173766.f90
@@ -0,0 +1,28 @@
+!RUN: bbc -emit-fir -o - %s 2>&1 | FileCheck %s
+module m
+  type samename
+    sequence
+    integer n
+  end type
+  interface samename
+  end interface
+  interface write(formatted)
+    module procedure :: write_formatted
+  end interface
+ contains
+  subroutine write_formatted(t, unit, iotype, v_list, iostat, iomsg)
+    type(samename), intent(in) :: t
+    integer, intent(in) :: unit
+    character(len=*), intent(in) :: iotype
+    integer, intent(in) :: v_list(:)
+    integer, intent(out) :: iostat
+    character(len=*), intent(inout) :: iomsg
+  end
+  subroutine test
+    print *, samename(123)
+  end
+end
+
+!CHECK: %[[VAL_8:.*]] = fir.address_of(@_QQMmFtest.nonTbpDefinedIoTable) : !fir.ref<tuple<i64, !fir.ref<!fir.array<1xtuple<!fir.ref<none>, !fir.ref<none>, i32, i8>>>, i1>>
+!CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<tuple<i64, !fir.ref<!fir.array<1xtuple<!fir.ref<none>, !fir.ref<none>, i32, i8>>>, i1>>) -> !fir.ref<none>
+!CHECK: %{{.*}} = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %{{.*}}, %[[VAL_9]]) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>, !fir.ref<none>) -> i1

@llvmbot
Copy link
Member

llvmbot commented Dec 28, 2025

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

Changes

The code that handles non-type-bound defined I/O for sequence types didn't allow for the type to be shadowed in its scope by a homonymous generic procedure interface.

Fixes #173766.


Full diff: https://github.com/llvm/llvm-project/pull/173783.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/runtime-type-info.cpp (+13-7)
  • (added) flang/test/Lower/bug173766.f90 (+28)
diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp
index bbaded36c62e3..8f92fda65685a 100644
--- a/flang/lib/Semantics/runtime-type-info.cpp
+++ b/flang/lib/Semantics/runtime-type-info.cpp
@@ -1394,13 +1394,19 @@ CollectNonTbpDefinedIoGenericInterfaces(
               // 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();
+                const Symbol *localDerived{&inScope->GetUltimate()};
+                if (const auto *generic{
+                        localDerived->detailsIf<GenericDetails>()}) {
+                  localDerived = generic->derivedType();
+                }
+                if (localDerived && localDerived->has<DerivedTypeDetails>()) {
+                  DerivedTypeSpec localDerivedType{
+                      inScope->name(), *localDerived};
+                  if (evaluate::DynamicType{derived, /*isPolymorphic=*/false}
+                          .IsTkCompatibleWith(evaluate::DynamicType{
+                              localDerivedType, /*iP=*/false})) {
+                    derivedScope = localDerived->scope();
+                  }
                 }
               }
             }
diff --git a/flang/test/Lower/bug173766.f90 b/flang/test/Lower/bug173766.f90
new file mode 100644
index 0000000000000..a9705f144c563
--- /dev/null
+++ b/flang/test/Lower/bug173766.f90
@@ -0,0 +1,28 @@
+!RUN: bbc -emit-fir -o - %s 2>&1 | FileCheck %s
+module m
+  type samename
+    sequence
+    integer n
+  end type
+  interface samename
+  end interface
+  interface write(formatted)
+    module procedure :: write_formatted
+  end interface
+ contains
+  subroutine write_formatted(t, unit, iotype, v_list, iostat, iomsg)
+    type(samename), intent(in) :: t
+    integer, intent(in) :: unit
+    character(len=*), intent(in) :: iotype
+    integer, intent(in) :: v_list(:)
+    integer, intent(out) :: iostat
+    character(len=*), intent(inout) :: iomsg
+  end
+  subroutine test
+    print *, samename(123)
+  end
+end
+
+!CHECK: %[[VAL_8:.*]] = fir.address_of(@_QQMmFtest.nonTbpDefinedIoTable) : !fir.ref<tuple<i64, !fir.ref<!fir.array<1xtuple<!fir.ref<none>, !fir.ref<none>, i32, i8>>>, i1>>
+!CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<tuple<i64, !fir.ref<!fir.array<1xtuple<!fir.ref<none>, !fir.ref<none>, i32, i8>>>, i1>>) -> !fir.ref<none>
+!CHECK: %{{.*}} = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %{{.*}}, %[[VAL_9]]) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>, !fir.ref<none>) -> i1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:fir-hlfir flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flang] crashes on derived type I/O when sequence type and interface have same name

2 participants