[llvm] [flang][Runtime] Reset the information of namelist formatting when invoking child I/O (PR #218314)
Yusuke MINATO via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 23 21:23:19 PDT 2026
https://github.com/yus3710-fj created https://github.com/llvm/llvm-project/pull/218314
The flag of namelist formatting is enabled when IONAME(OutputNamelist) or IONAME(InputNamelist) is called, but it was never disabled afterward.
This patch disables the flag when invoking child I/O, as child I/O cannot use namelist formatting.
Fixes #201516
>From 87914ceac4d344a6dfe347e410af1928665b6ad3 Mon Sep 17 00:00:00 2001
From: Yusuke MINATO <minato.yusuke at fujitsu.com>
Date: Wed, 29 Jul 2026 17:08:36 +0900
Subject: [PATCH 1/2] [flang][Runtime] Reset the information of namelist
formatting when invoking child I/O
---
flang-rt/lib/runtime/io-stmt.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/flang-rt/lib/runtime/io-stmt.cpp b/flang-rt/lib/runtime/io-stmt.cpp
index 08931fc781428..aff36ece27ef7 100644
--- a/flang-rt/lib/runtime/io-stmt.cpp
+++ b/flang-rt/lib/runtime/io-stmt.cpp
@@ -988,7 +988,9 @@ template <Direction DIR>
ChildIoStatementState<DIR>::ChildIoStatementState(
ChildIo &child, const char *sourceFile, int sourceLine)
: IoStatementBase{sourceFile, sourceLine}, child_{child},
- mutableModes_{child.parent().mutableModes()} {}
+ mutableModes_{child.parent().mutableModes()} {
+ mutableModes_.inNamelist = false;
+}
template <Direction DIR>
const NonTbpDefinedIoTable *
>From c666657a7d8b792d6dd71dc1dae5a58dc257ce30 Mon Sep 17 00:00:00 2001
From: Yusuke MINATO <minato.yusuke at fujitsu.com>
Date: Wed, 5 Aug 2026 14:11:43 +0900
Subject: [PATCH 2/2] Add tests
---
.../{lib => include/flang-rt}/runtime/unit.h | 0
flang-rt/lib/runtime/descriptor-io.cpp | 2 +-
flang-rt/lib/runtime/execute.cpp | 2 +-
flang-rt/lib/runtime/extensions.cpp | 2 +-
flang-rt/lib/runtime/external-unit.cpp | 1 -
flang-rt/lib/runtime/io-api-common.h | 2 +-
flang-rt/lib/runtime/io-api-minimal.cpp | 2 +-
flang-rt/lib/runtime/io-api.cpp | 2 +-
flang-rt/lib/runtime/io-stmt-minimal.cpp | 2 +-
flang-rt/lib/runtime/io-stmt.cpp | 2 +-
flang-rt/lib/runtime/pseudo-unit.cpp | 2 +-
flang-rt/lib/runtime/stop.cpp | 2 +-
flang-rt/lib/runtime/unit-map.h | 2 +-
flang-rt/lib/runtime/unit.cpp | 2 +-
flang-rt/test/Driver/iotype.f90 | 59 +++++++++++++++++++
flang-rt/unittests/Runtime/CMakeLists.txt | 1 +
flang-rt/unittests/Runtime/ChildIO.cpp | 35 +++++++++++
17 files changed, 107 insertions(+), 13 deletions(-)
rename flang-rt/{lib => include/flang-rt}/runtime/unit.h (100%)
create mode 100644 flang-rt/test/Driver/iotype.f90
create mode 100644 flang-rt/unittests/Runtime/ChildIO.cpp
diff --git a/flang-rt/lib/runtime/unit.h b/flang-rt/include/flang-rt/runtime/unit.h
similarity index 100%
rename from flang-rt/lib/runtime/unit.h
rename to flang-rt/include/flang-rt/runtime/unit.h
diff --git a/flang-rt/lib/runtime/descriptor-io.cpp b/flang-rt/lib/runtime/descriptor-io.cpp
index 79880f1e916ba..3b8a65d1ad9cf 100644
--- a/flang-rt/lib/runtime/descriptor-io.cpp
+++ b/flang-rt/lib/runtime/descriptor-io.cpp
@@ -9,12 +9,12 @@
#include "descriptor-io.h"
#include "edit-input.h"
#include "edit-output.h"
-#include "unit.h"
#include "flang-rt/runtime/descriptor.h"
#include "flang-rt/runtime/io-stmt.h"
#include "flang-rt/runtime/namelist.h"
#include "flang-rt/runtime/terminator.h"
#include "flang-rt/runtime/type-info.h"
+#include "flang-rt/runtime/unit.h"
#include "flang-rt/runtime/work-queue.h"
#include "flang/Common/optional.h"
#include "flang/Common/restorer.h"
diff --git a/flang-rt/lib/runtime/execute.cpp b/flang-rt/lib/runtime/execute.cpp
index 4fd6a1e060218..875cb597fa071 100644
--- a/flang-rt/lib/runtime/execute.cpp
+++ b/flang-rt/lib/runtime/execute.cpp
@@ -7,12 +7,12 @@
//===----------------------------------------------------------------------===//
#include "flang/Runtime/execute.h"
-#include "unit.h"
#include "flang-rt/runtime/descriptor.h"
#include "flang-rt/runtime/environment.h"
#include "flang-rt/runtime/stat.h"
#include "flang-rt/runtime/terminator.h"
#include "flang-rt/runtime/tools.h"
+#include "flang-rt/runtime/unit.h"
#include <cstdio>
#include <cstdlib>
#include <errno.h>
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index ee084fdd72bd8..b159c7747726f 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -10,12 +10,12 @@
// extensions that will eventually be implemented in Fortran.
#include "flang/Runtime/extensions.h"
-#include "unit.h"
#include "flang-rt/runtime/descriptor.h"
#include "flang-rt/runtime/environment.h"
#include "flang-rt/runtime/lock.h"
#include "flang-rt/runtime/terminator.h"
#include "flang-rt/runtime/tools.h"
+#include "flang-rt/runtime/unit.h"
#include "flang/Runtime/command.h"
#include "flang/Runtime/entry-names.h"
#include "flang/Runtime/io-api.h"
diff --git a/flang-rt/lib/runtime/external-unit.cpp b/flang-rt/lib/runtime/external-unit.cpp
index 25e6981334f75..b4eaf2e85fc9a 100644
--- a/flang-rt/lib/runtime/external-unit.cpp
+++ b/flang-rt/lib/runtime/external-unit.cpp
@@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//
#include "unit-map.h"
-#include "unit.h"
#include "flang-rt/runtime/io-error.h"
#include "flang-rt/runtime/lock.h"
#include "flang-rt/runtime/tools.h"
diff --git a/flang-rt/lib/runtime/io-api-common.h b/flang-rt/lib/runtime/io-api-common.h
index adf299e4bca53..040d26b7e3e4b 100644
--- a/flang-rt/lib/runtime/io-api-common.h
+++ b/flang-rt/lib/runtime/io-api-common.h
@@ -9,9 +9,9 @@
#ifndef FLANG_RT_RUNTIME_IO_API_COMMON_H_
#define FLANG_RT_RUNTIME_IO_API_COMMON_H_
-#include "unit.h"
#include "flang-rt/runtime/io-stmt.h"
#include "flang-rt/runtime/terminator.h"
+#include "flang-rt/runtime/unit.h"
#include "flang/Common/api-attrs.h"
#include "flang/Common/optional.h"
#include "flang/Runtime/io-api.h"
diff --git a/flang-rt/lib/runtime/io-api-minimal.cpp b/flang-rt/lib/runtime/io-api-minimal.cpp
index 299d87179f1a3..9c64754e66617 100644
--- a/flang-rt/lib/runtime/io-api-minimal.cpp
+++ b/flang-rt/lib/runtime/io-api-minimal.cpp
@@ -11,11 +11,11 @@
#include "edit-output.h"
#include "io-api-common.h"
-#include "unit.h"
#include "flang-rt/runtime/format.h"
#include "flang-rt/runtime/io-stmt.h"
#include "flang-rt/runtime/terminator.h"
#include "flang-rt/runtime/tools.h"
+#include "flang-rt/runtime/unit.h"
#include "flang/Runtime/io-api.h"
namespace Fortran::runtime::io {
diff --git a/flang-rt/lib/runtime/io-api.cpp b/flang-rt/lib/runtime/io-api.cpp
index 2c97a39ea2555..28f16872ddada 100644
--- a/flang-rt/lib/runtime/io-api.cpp
+++ b/flang-rt/lib/runtime/io-api.cpp
@@ -18,7 +18,6 @@
#include "edit-input.h"
#include "edit-output.h"
#include "io-api-common.h"
-#include "unit.h"
#include "flang-rt/runtime/descriptor.h"
#include "flang-rt/runtime/environment.h"
#include "flang-rt/runtime/format.h"
@@ -26,6 +25,7 @@
#include "flang-rt/runtime/memory.h"
#include "flang-rt/runtime/terminator.h"
#include "flang-rt/runtime/tools.h"
+#include "flang-rt/runtime/unit.h"
#include "flang/Common/optional.h"
#include <cstdlib>
#include <memory>
diff --git a/flang-rt/lib/runtime/io-stmt-minimal.cpp b/flang-rt/lib/runtime/io-stmt-minimal.cpp
index a0e91d37a3f37..ca52fbd168434 100644
--- a/flang-rt/lib/runtime/io-stmt-minimal.cpp
+++ b/flang-rt/lib/runtime/io-stmt-minimal.cpp
@@ -9,8 +9,8 @@
// Implements the subset of the I/O statement API needed for basic
// list-directed output (PRINT *) of intrinsic types.
-#include "unit.h"
#include "flang-rt/runtime/io-stmt.h"
+#include "flang-rt/runtime/unit.h"
#include <algorithm>
namespace Fortran::runtime::io {
diff --git a/flang-rt/lib/runtime/io-stmt.cpp b/flang-rt/lib/runtime/io-stmt.cpp
index aff36ece27ef7..05032a1e9da34 100644
--- a/flang-rt/lib/runtime/io-stmt.cpp
+++ b/flang-rt/lib/runtime/io-stmt.cpp
@@ -7,12 +7,12 @@
//===----------------------------------------------------------------------===//
#include "flang-rt/runtime/io-stmt.h"
-#include "unit.h"
#include "flang-rt/runtime/connection.h"
#include "flang-rt/runtime/emit-encoded.h"
#include "flang-rt/runtime/format.h"
#include "flang-rt/runtime/memory.h"
#include "flang-rt/runtime/tools.h"
+#include "flang-rt/runtime/unit.h"
#include "flang-rt/runtime/utf.h"
#include <algorithm>
#include <cstdio>
diff --git a/flang-rt/lib/runtime/pseudo-unit.cpp b/flang-rt/lib/runtime/pseudo-unit.cpp
index 7d6ddd9d8e2a4..c4ec1acaf7821 100644
--- a/flang-rt/lib/runtime/pseudo-unit.cpp
+++ b/flang-rt/lib/runtime/pseudo-unit.cpp
@@ -11,9 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "unit.h"
#include "flang-rt/runtime/io-error.h"
#include "flang-rt/runtime/tools.h"
+#include "flang-rt/runtime/unit.h"
#if defined(RT_USE_PSEUDO_FILE_UNIT)
#include <cstdio>
diff --git a/flang-rt/lib/runtime/stop.cpp b/flang-rt/lib/runtime/stop.cpp
index 5abb80af7e66d..b4508e0b7d0bc 100644
--- a/flang-rt/lib/runtime/stop.cpp
+++ b/flang-rt/lib/runtime/stop.cpp
@@ -8,11 +8,11 @@
#include "flang/Runtime/stop.h"
#include "config.h"
-#include "unit.h"
#include "flang-rt/runtime/environment.h"
#include "flang-rt/runtime/file.h"
#include "flang-rt/runtime/io-error.h"
#include "flang-rt/runtime/terminator.h"
+#include "flang-rt/runtime/unit.h"
#include <cfenv>
#include <cstdio>
#include <cstdlib>
diff --git a/flang-rt/lib/runtime/unit-map.h b/flang-rt/lib/runtime/unit-map.h
index fa61288a1e18d..f8e233e72d5bb 100644
--- a/flang-rt/lib/runtime/unit-map.h
+++ b/flang-rt/lib/runtime/unit-map.h
@@ -12,9 +12,9 @@
#ifndef FLANG_RT_RUNTIME_UNIT_MAP_H_
#define FLANG_RT_RUNTIME_UNIT_MAP_H_
-#include "unit.h"
#include "flang-rt/runtime/lock.h"
#include "flang-rt/runtime/memory.h"
+#include "flang-rt/runtime/unit.h"
#include "flang/Common/fast-int-set.h"
#include <cstdint>
#include <cstdlib>
diff --git a/flang-rt/lib/runtime/unit.cpp b/flang-rt/lib/runtime/unit.cpp
index c577ae7673127..c6839e1e19e48 100644
--- a/flang-rt/lib/runtime/unit.cpp
+++ b/flang-rt/lib/runtime/unit.cpp
@@ -10,7 +10,7 @@
// RT_USE_PSEUDO_FILE_UNIT=0 and RT_USE_PSEUDO_FILE_UNIT=1.
//
//===----------------------------------------------------------------------===//
-#include "unit.h"
+#include "flang-rt/runtime/unit.h"
#include "flang-rt/runtime/io-error.h"
#include "flang-rt/runtime/lock.h"
#include "flang-rt/runtime/tools.h"
diff --git a/flang-rt/test/Driver/iotype.f90 b/flang-rt/test/Driver/iotype.f90
new file mode 100644
index 0000000000000..aceb2a8682ab2
--- /dev/null
+++ b/flang-rt/test/Driver/iotype.f90
@@ -0,0 +1,59 @@
+! Verify that the value of iotype is correct when writing a derived type
+! with a derived type component to a namelist.
+
+! RUN: %flang %isysroot -L"%libdir" %s -o %t
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t
+
+module iotype_mod
+ type ty2
+ integer :: x
+ contains
+ procedure :: type_2_prc
+ generic :: write(formatted) => type_2_prc
+ end type
+
+ type ty1
+ TYPE (ty2) :: t1
+ contains
+ procedure :: type_1_prc
+ generic :: write(formatted) => type_1_prc
+ end type
+
+ character(14) :: ch_iotype_1='xxxxxxx'
+ character(14) :: ch_iotype_2='yyyyyyy'
+contains
+ subroutine type_1_prc(dtv, unit, iotype, vlist, iostat, iomsg)
+ class(ty1), intent(in) :: dtv
+ integer, intent(in) :: unit
+ character(*), intent(in) :: iotype
+ integer, intent(in) :: vlist(:)
+ integer, intent(out) :: iostat
+ character(*), intent(inout) :: iomsg
+ ch_iotype_1 =iotype
+ write(unit,*,iostat=iostat,iomsg=iomsg) dtv%t1
+ end subroutine
+
+ subroutine type_2_prc(dtv, unit, iotype, vlist, iostat, iomsg)
+ class(ty2), intent(in) :: dtv
+ integer, intent(in) :: unit
+ character(*), intent(in) :: iotype
+ integer, intent(in) :: vlist(:)
+ integer, intent(out) :: iostat
+ character(*), intent(inout) :: iomsg
+ ch_iotype_2 =iotype
+ write(unit,*,iostat=iostat,iomsg=iomsg) dtv%x
+ end subroutine
+end module
+
+program main
+ USE iotype_mod
+ type(ty1) :: obj
+ namelist /NAME/obj
+ obj%t1%x=9
+
+ open(10,status="scratch")
+ WRITE(10,NML=NAME)
+
+ if (ch_iotype_1/='NAMELIST') error stop 1
+ if (ch_iotype_2/='LISTDIRECTED') error stop 2
+end program
diff --git a/flang-rt/unittests/Runtime/CMakeLists.txt b/flang-rt/unittests/Runtime/CMakeLists.txt
index ddabe346b54d1..112d864e26a53 100644
--- a/flang-rt/unittests/Runtime/CMakeLists.txt
+++ b/flang-rt/unittests/Runtime/CMakeLists.txt
@@ -13,6 +13,7 @@ add_flangrt_unittest(RuntimeTests
Assign.cpp
BufferTest.cpp
CharacterTest.cpp
+ ChildIO.cpp
CommandTest.cpp
Complex.cpp
CrashHandlerFixture.cpp
diff --git a/flang-rt/unittests/Runtime/ChildIO.cpp b/flang-rt/unittests/Runtime/ChildIO.cpp
new file mode 100644
index 0000000000000..27ee21c4d3395
--- /dev/null
+++ b/flang-rt/unittests/Runtime/ChildIO.cpp
@@ -0,0 +1,35 @@
+//===-- unittests/Runtime/ChildIO.cpp --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CrashHandlerFixture.h"
+#include "gtest/gtest.h"
+#include "flang-rt/runtime/unit.h"
+#include "flang/Runtime/io-api.h"
+
+using namespace Fortran::runtime;
+using namespace Fortran::runtime::io;
+
+struct ChildIOTests : CrashHandlerFixture {};
+
+TEST(ChildIOTests, InNamelist) {
+ // CHARACTER(LEN=10) :: output
+ static constexpr int bufferSize{10};
+ char output[bufferSize];
+
+ // WRITE(UNIT=output,NML=...)
+ Cookie parentCookie{IONAME(BeginInternalListOutput)(output, bufferSize)};
+ parentCookie->mutableModes().inNamelist = true;
+
+ // invoke child I/O (DTIO)
+ IoErrorHandler &handler{parentCookie->GetIoErrorHandler()};
+ ExternalFileUnit *newUnit{&ExternalFileUnit::NewUnit(handler, true)};
+ [[maybe_unused]] ChildIo &child{newUnit->PushChildIo(*parentCookie)};
+ Cookie childCookie{IONAME(BeginExternalListOutput)(
+ newUnit->unitNumber(), __FILE__, __LINE__)};
+ ASSERT_FALSE(childCookie->mutableModes().inNamelist);
+}
More information about the llvm-commits
mailing list