[flang-commits] [flang] [flang] Fix variable unformatted I/O bug with output after input (PR #92828)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon May 20 15:17:51 PDT 2024
https://github.com/klausler created https://github.com/llvm/llvm-project/pull/92828
When reading variable-length unformatted records, the external I/O library frames the input buffer so that the footer of the previous record remains in frame. This is done so that a BACKSPACE doesn't have to do an extra read to get the length of the previous record before repositioning over it.
When switching from input to output to overwrite or append new records after reading any, it is necessary to undo this framing of the last word in the previous record, since the new output isn't going to define it in the buffer and it'll be overwritten in the filesystem with garbage.
>From 590bf1570b19f196c4868c49d6a6ca29cca88812 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Mon, 20 May 2024 15:12:25 -0700
Subject: [PATCH] [flang] Fix variable unformatted I/O bug with output after
input
When reading variable-length unformatted records, the external I/O
library frames the input buffer so that the footer of the previous
record remains in frame. This is done so that a BACKSPACE doesn't
have to do an extra read to get the length of the previous record
before repositioning over it.
When switching from input to output to overwrite or append new
records after reading any, it is necessary to undo this framing of
the last word in the previous record, since the new output isn't
going to define it in the buffer and it'll be overwritten in the
filesystem with garbage.
---
flang/runtime/external-unit.cpp | 8 +++++++-
flang/runtime/unit.cpp | 1 +
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/flang/runtime/external-unit.cpp b/flang/runtime/external-unit.cpp
index b48549d54587e..4bfa218bb7769 100644
--- a/flang/runtime/external-unit.cpp
+++ b/flang/runtime/external-unit.cpp
@@ -214,6 +214,13 @@ Iostat ExternalFileUnit::SetDirection(Direction direction) {
}
} else {
if (mayWrite()) {
+ if (direction_ == Direction::Input) {
+ // Don't retain any input data from previous record, like a
+ // variable-length unformatted record footer, in the frame,
+ // since we're going start writing frames.
+ frameOffsetInFile_ += recordOffsetInFrame_;
+ recordOffsetInFrame_ = 0;
+ }
direction_ = Direction::Output;
return IostatOk;
} else {
@@ -332,5 +339,4 @@ bool ExternalFileUnit::Wait(int id) {
}
} // namespace Fortran::runtime::io
-
#endif // !defined(RT_USE_PSEUDO_FILE_UNIT)
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 3b42f45d55884..a11f444d8d754 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -265,6 +265,7 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
furthestPositionInRecord =
std::max(furthestPositionInRecord, positionInRecord);
frameOffsetInFile_ += recordOffsetInFrame_ + furthestPositionInRecord;
+ recordOffsetInFrame_ = 0;
}
BeginRecord();
}
More information about the flang-commits
mailing list