Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang][runtime] Handle end of internal output correctly #84994

Merged
merged 1 commit into from
Mar 13, 2024

Conversation

klausler
Copy link
Contributor

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.

@llvmbot llvmbot added flang:runtime flang Flang issues not falling into any other category labels Mar 12, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 12, 2024

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

Changes

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.


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

4 Files Affected:

  • (modified) flang/runtime/internal-unit.cpp (+5-1)
  • (modified) flang/runtime/io-stmt.cpp (+12-4)
  • (modified) flang/runtime/io-stmt.h (+1)
  • (modified) flang/unittests/Runtime/NumericalFormatTest.cpp (+2-1)
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(

@klausler klausler force-pushed the bug1548 branch 2 times, most recently from 18ef785 to b6aeb77 Compare March 13, 2024 00:06
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.

Further, a signed integer in a format must have a digit, and can appear
only as the scale factor before a P control edit descriptor.
@klausler klausler merged commit fc71a49 into llvm:main Mar 13, 2024
3 of 4 checks passed
@klausler klausler deleted the bug1548 branch March 13, 2024 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:runtime flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants