From 1a65d09dcf9b9bed89f8c4fd848a056ebb507597 Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Thu, 7 Jul 2022 14:51:40 -0700 Subject: [PATCH] [flang][runtime] Keep frame buffer in sync with file when truncating When the I/O runtime is truncating an external file due to an implied ENDFILE or explicit ENDFILE, ensure that the unit's frame buffer for the file discards any data that have become obsolete. This bug caused trouble with ACCESS='STREAM' I/O using POS= on a WRITE, but it may have not been limited to that scenario. Differential Revision: https://reviews.llvm.org/D129673 --- flang/runtime/buffer.h | 9 +++++++++ flang/runtime/unit.cpp | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/flang/runtime/buffer.h b/flang/runtime/buffer.h index 0bc3e0a37ded..a77a5a5dda5c 100644 --- a/flang/runtime/buffer.h +++ b/flang/runtime/buffer.h @@ -128,6 +128,15 @@ public: } } + void TruncateFrame(std::int64_t at, IoErrorHandler &handler) { + RUNTIME_CHECK(handler, !dirty_); + if (at <= fileOffset_) { + Reset(at); + } else if (at < fileOffset_ + length_) { + length_ = at - fileOffset_; + } + } + private: STORE &Store() { return static_cast(*this); } diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index a96b43d6a2c9..018c4332415d 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -898,9 +898,9 @@ void ExternalFileUnit::DoEndfile(IoErrorHandler &handler) { } frameOffsetInFile_ += recordOffsetInFrame_ + furthestPositionInRecord; recordOffsetInFrame_ = 0; - // Flush (if dirty) and reset the frame (even if reading) - WriteFrame(frameOffsetInFile_, 0, handler); + FlushOutput(handler); Truncate(frameOffsetInFile_, handler); + TruncateFrame(frameOffsetInFile_, handler); BeginRecord(); impliedEndfile_ = false; }