[flang-commits] [flang] [flang][runtime] Handle end of internal output correctly (PR #84994)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Tue Mar 12 16:29:54 PDT 2024


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/84994

At the end of an internal output statement, be sure to finish any following control edit descriptors in the format (if any), and (for output) advance to the next record.  Return the right I/O error status code if output overruns the buffer.

>From a81a5e5bc86178bef4cea84b7f988d2a4584c814 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Tue, 12 Mar 2024 16:22:47 -0700
Subject: [PATCH] [flang][runtime] Handle end of internal output correctly

At the end of an internal output statement, be sure to finish
any following control edit descriptors in the format (if any),
and (for output) advance to the next record.  Return the right
I/O error status code if output overruns the buffer.
---
 flang/runtime/internal-unit.cpp                 |  6 +++++-
 flang/runtime/io-stmt.cpp                       | 16 ++++++++++++----
 flang/runtime/io-stmt.h                         |  1 +
 flang/unittests/Runtime/NumericalFormatTest.cpp |  3 ++-
 4 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/flang/runtime/internal-unit.cpp b/flang/runtime/internal-unit.cpp
index e3fffaa6f378ff..46d442a7cdd726 100644
--- a/flang/runtime/internal-unit.cpp
+++ b/flang/runtime/internal-unit.cpp
@@ -109,7 +109,11 @@ std::size_t InternalDescriptorUnit<DIR>::GetNextInputBytes(
 template <Direction DIR>
 bool InternalDescriptorUnit<DIR>::AdvanceRecord(IoErrorHandler &handler) {
   if (currentRecordNumber >= endfileRecordNumber.value_or(0)) {
-    handler.SignalEnd();
+    if constexpr (DIR == Direction::Input) {
+      handler.SignalEnd();
+    } else {
+      handler.SignalError(IostatInternalWriteOverrun);
+    }
     return false;
   }
   if constexpr (DIR == Direction::Output) {
diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index 3ec01ffba9bf06..bdee947481bf98 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -118,6 +118,16 @@ template <Direction DIR> void InternalIoStatementState<DIR>::BackspaceRecord() {
   unit_.BackspaceRecord(*this);
 }
 
+template <Direction DIR>
+void InternalIoStatementState<DIR>::CompleteOperation() {
+  if (!this->completedOperation()) {
+    if constexpr (DIR == Direction::Output) {
+      unit_.AdvanceRecord(*this);
+    }
+    IoStatementBase::CompleteOperation();
+  }
+}
+
 template <Direction DIR> int InternalIoStatementState<DIR>::EndIoStatement() {
   if constexpr (DIR == Direction::Output) {
     unit_.EndIoStatement(); // fill
@@ -164,10 +174,8 @@ InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState(
 template <Direction DIR, typename CHAR>
 void InternalFormattedIoStatementState<DIR, CHAR>::CompleteOperation() {
   if (!this->completedOperation()) {
-    if constexpr (DIR == Direction::Output) {
-      format_.Finish(*this); // ignore any remaining input positioning actions
-    }
-    IoStatementBase::CompleteOperation();
+    format_.Finish(*this);
+    InternalIoStatementState<DIR>::CompleteOperation();
   }
 }
 
diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 0b6bcbd9af025a..2deef950d7f63e 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -346,6 +346,7 @@ class InternalIoStatementState : public IoStatementBase,
       const char *sourceFile = nullptr, int sourceLine = 0);
   InternalIoStatementState(
       const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0);
+  void CompleteOperation();
   int EndIoStatement();
 
   bool Emit(const char *data, std::size_t bytes, std::size_t elementBytes = 0);
diff --git a/flang/unittests/Runtime/NumericalFormatTest.cpp b/flang/unittests/Runtime/NumericalFormatTest.cpp
index 37eecd7708a1eb..ffde461fd82324 100644
--- a/flang/unittests/Runtime/NumericalFormatTest.cpp
+++ b/flang/unittests/Runtime/NumericalFormatTest.cpp
@@ -104,7 +104,7 @@ TEST(IOApiTests, HelloWorldOutputTest) {
 
 TEST(IOApiTests, MultilineOutputTest) {
   // Allocate buffer for multiline output
-  static constexpr int numLines{5};
+  static constexpr int numLines{6};
   static constexpr int lineLength{32};
   char buffer[numLines][lineLength];
 
@@ -159,6 +159,7 @@ TEST(IOApiTests, MultilineOutputTest) {
                                   "                                "
                                   "789                 abcd 666 777"
                                   " 888 999                        "
+                                  "                                "
                                   "................................"};
   // Ensure formatted string matches expected output
   EXPECT_TRUE(



More information about the flang-commits mailing list