[flang-commits] [flang] e29c9d7 - [flang] Fix WRITE after BACKSPACE
peter klausler via flang-commits
flang-commits at lists.llvm.org
Thu Oct 1 10:34:13 PDT 2020
Author: peter klausler
Date: 2020-10-01T10:33:31-07:00
New Revision: e29c9d77f128e7ef9b2b5f8f09fb06b01a9dad3a
URL: https://github.com/llvm/llvm-project/commit/e29c9d77f128e7ef9b2b5f8f09fb06b01a9dad3a
DIFF: https://github.com/llvm/llvm-project/commit/e29c9d77f128e7ef9b2b5f8f09fb06b01a9dad3a.diff
LOG: [flang] Fix WRITE after BACKSPACE
A WRITE to an unformatted sequential variable-length unit after
a BACKSPACE needs to forget its previous knowledge of the length
of the record that's about to be overwritten, and a BACKSPACE
after an ENDFILE or at the start of the file needs to be a no-op.
Differential revision: https://reviews.llvm.org/D88675
Added:
Modified:
flang/runtime/io-api.cpp
flang/runtime/unit.cpp
Removed:
################################################################################
diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index 304c40e871f4..edd338af0fa7 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -235,6 +235,7 @@ Cookie BeginUnformattedIO(
if (unit.access == Access::Sequential && !unit.isFixedRecordLength) {
// Create space for (sub)record header to be completed by
// UnformattedIoStatementState<Direction::Output>::EndIoStatement()
+ unit.recordLength.reset(); // in case of prior BACKSPACE
io.Emit("\0\0\0\0", 4); // placeholder for record length header
}
}
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index bcb8a478ad59..77b7a74551d8 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -132,16 +132,17 @@ void ExternalFileUnit::OpenUnit(OpenStatus status, std::optional<Action> action,
static_cast<std::intmax_t>(*totalBytes));
}
}
+ endfileRecordNumber.reset();
+ currentRecordNumber = 1;
+ if (totalBytes && recordLength && *recordLength) {
+ endfileRecordNumber = 1 + (*totalBytes / *recordLength);
+ }
if (position == Position::Append) {
- if (totalBytes && recordLength && *recordLength) {
- endfileRecordNumber = 1 + (*totalBytes / *recordLength);
- } else {
+ if (!endfileRecordNumber) {
// Fake it so that we can backspace relative from the end
- endfileRecordNumber = std::numeric_limits<std::int64_t>::max() - 1;
+ endfileRecordNumber = std::numeric_limits<std::int64_t>::max() - 2;
}
currentRecordNumber = *endfileRecordNumber;
- } else {
- currentRecordNumber = 1;
}
}
@@ -374,7 +375,9 @@ void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_);
beganReadingRecord_ = false;
- if (access == Access::Sequential) {
+ if (handler.GetIoStat() != IostatOk) {
+ // avoid bogus crashes in END/ERR circumstances
+ } else if (access == Access::Sequential) {
RUNTIME_CHECK(handler, recordLength.has_value());
if (isFixedRecordLength) {
frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
@@ -430,16 +433,22 @@ void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {
handler.SignalError(IostatBackspaceNonSequential,
"BACKSPACE(UNIT=%d) on non-sequential file", unitNumber());
} else {
- DoImpliedEndfile(handler);
- --currentRecordNumber;
- BeginRecord();
- if (isFixedRecordLength) {
- BackspaceFixedRecord(handler);
- } else if (isUnformatted) {
- BackspaceVariableUnformattedRecord(handler);
+ if (endfileRecordNumber && currentRecordNumber > *endfileRecordNumber) {
+ // BACKSPACE after ENDFILE
} else {
- BackspaceVariableFormattedRecord(handler);
+ DoImpliedEndfile(handler);
+ if (frameOffsetInFile_ + recordOffsetInFrame_ > 0) {
+ --currentRecordNumber;
+ if (isFixedRecordLength) {
+ BackspaceFixedRecord(handler);
+ } else if (isUnformatted) {
+ BackspaceVariableUnformattedRecord(handler);
+ } else {
+ BackspaceVariableFormattedRecord(handler);
+ }
+ }
}
+ BeginRecord();
}
}
@@ -456,8 +465,12 @@ void ExternalFileUnit::Endfile(IoErrorHandler &handler) {
} else if (!mayWrite()) {
handler.SignalError(IostatEndfileUnwritable,
"ENDFILE(UNIT=%d) on read-only file", unitNumber());
+ } else if (endfileRecordNumber &&
+ currentRecordNumber > *endfileRecordNumber) {
+ // ENDFILE after ENDFILE
} else {
DoEndfile(handler);
+ ++currentRecordNumber;
}
}
@@ -469,7 +482,6 @@ void ExternalFileUnit::Rewind(IoErrorHandler &handler) {
DoImpliedEndfile(handler);
SetPosition(0);
currentRecordNumber = 1;
- // TODO: reset endfileRecordNumber?
}
}
More information about the flang-commits
mailing list