[flang-commits] [flang] d771245 - [flang] Fix READ/WRITE with POS= on stream units, with refactoring
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Jun 23 09:17:00 PDT 2022
Author: Peter Klausler
Date: 2022-06-23T09:16:49-07:00
New Revision: d771245a9dd81c374e7ff34581a2f7adaf74fc38
URL: https://github.com/llvm/llvm-project/commit/d771245a9dd81c374e7ff34581a2f7adaf74fc38
DIFF: https://github.com/llvm/llvm-project/commit/d771245a9dd81c374e7ff34581a2f7adaf74fc38.diff
LOG: [flang] Fix READ/WRITE with POS= on stream units, with refactoring
First, ExternalFileUnit::SetPosition was being used both as a utility
within the class' member functions as well as an API from I/O statement
processing. Make it private, and add APIs for SetStreamPos and SetDirectRec.
Second, ensure that SetStreamPos for POS= positioning in a stream
doesn't leave the current record number and endfile record number
in an arbitrary state. In stream I/O they are used only to manage
end-of-file detection, and shouldn't produce false positive results
from IsAtEnd() after repositioning.
Differential Revision: https://reviews.llvm.org/D128388
Added:
Modified:
flang/runtime/io-api.cpp
flang/runtime/unit.cpp
flang/runtime/unit.h
Removed:
################################################################################
diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index d730dd844c2ac..f3efaa9635749 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -634,44 +634,22 @@ bool IONAME(SetPad)(Cookie cookie, const char *keyword, std::size_t length) {
bool IONAME(SetPos)(Cookie cookie, std::int64_t pos) {
IoStatementState &io{*cookie};
- ConnectionState &connection{io.GetConnectionState()};
IoErrorHandler &handler{io.GetIoErrorHandler()};
- if (connection.access != Access::Stream) {
- handler.SignalError("POS= may not appear unless ACCESS='STREAM'");
- return false;
- }
- if (pos < 1) { // POS=1 is beginning of file (12.6.2.11)
- handler.SignalError("POS=%zd is invalid", static_cast<std::intmax_t>(pos));
- return false;
- }
if (auto *unit{io.GetExternalFileUnit()}) {
- unit->SetPosition(pos - 1, handler);
- return true;
+ return unit->SetStreamPos(pos, handler);
} else if (!io.get_if<ErroneousIoStatementState>()) {
- io.GetIoErrorHandler().Crash("SetPos() called on internal unit");
+ handler.Crash("SetPos() called on internal unit");
}
return false;
}
bool IONAME(SetRec)(Cookie cookie, std::int64_t rec) {
IoStatementState &io{*cookie};
- ConnectionState &connection{io.GetConnectionState()};
IoErrorHandler &handler{io.GetIoErrorHandler()};
- if (connection.access != Access::Direct) {
- handler.SignalError("REC= may not appear unless ACCESS='DIRECT'");
- return false;
- }
- if (!connection.openRecl) {
- handler.SignalError("RECL= was not specified");
- return false;
- }
- if (rec < 1) {
- handler.SignalError("REC=%zd is invalid", static_cast<std::intmax_t>(rec));
- return false;
- }
- connection.currentRecordNumber = rec;
if (auto *unit{io.GetExternalFileUnit()}) {
- unit->SetPosition((rec - 1) * *connection.openRecl, handler);
+ unit->SetDirectRec(rec, handler);
+ } else if (!io.get_if<ErroneousIoStatementState>()) {
+ handler.Crash("SetRec() called on internal unit");
}
return true;
}
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 729bce8ddfa16..e0daf8c24a238 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -655,6 +655,45 @@ void ExternalFileUnit::SetPosition(std::int64_t pos, IoErrorHandler &handler) {
BeginRecord();
}
+bool ExternalFileUnit::SetStreamPos(
+ std::int64_t oneBasedPos, IoErrorHandler &handler) {
+ if (access != Access::Stream) {
+ handler.SignalError("POS= may not appear unless ACCESS='STREAM'");
+ return false;
+ }
+ if (oneBasedPos < 1) { // POS=1 is beginning of file (12.6.2.11)
+ handler.SignalError(
+ "POS=%zd is invalid", static_cast<std::intmax_t>(oneBasedPos));
+ return false;
+ }
+ SetPosition(oneBasedPos - 1, handler);
+ // We no longer know which record we're in. Set currentRecordNumber to
+ // a large value from whence we can both advance and backspace.
+ currentRecordNumber = std::numeric_limits<std::int64_t>::max() / 2;
+ endfileRecordNumber.reset();
+ return true;
+}
+
+bool ExternalFileUnit::SetDirectRec(
+ std::int64_t oneBasedRec, IoErrorHandler &handler) {
+ if (access != Access::Direct) {
+ handler.SignalError("REC= may not appear unless ACCESS='DIRECT'");
+ return false;
+ }
+ if (!openRecl) {
+ handler.SignalError("RECL= was not specified");
+ return false;
+ }
+ if (oneBasedRec < 1) {
+ handler.SignalError(
+ "REC=%zd is invalid", static_cast<std::intmax_t>(oneBasedRec));
+ return false;
+ }
+ currentRecordNumber = oneBasedRec;
+ SetPosition((oneBasedRec - 1) * *openRecl, handler);
+ return true;
+}
+
void ExternalFileUnit::EndIoStatement() {
io_.reset();
u_.emplace<std::monostate>();
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index 03a4a44fa95af..76666c65ab68c 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -94,7 +94,8 @@ class ExternalFileUnit : public ConnectionState,
void Endfile(IoErrorHandler &);
void Rewind(IoErrorHandler &);
void EndIoStatement();
- void SetPosition(std::int64_t, IoErrorHandler &); // zero-based
+ bool SetStreamPos(std::int64_t, IoErrorHandler &); // one-based, for POS=
+ bool SetDirectRec(std::int64_t, IoErrorHandler &); // one-based, for REC=
std::int64_t InquirePos() const {
// 12.6.2.11 defines POS=1 as the beginning of file
return frameOffsetInFile_ + recordOffsetInFrame_ + positionInRecord + 1;
@@ -110,6 +111,7 @@ class ExternalFileUnit : public ConnectionState,
private:
static UnitMap &GetUnitMap();
const char *FrameNextInput(IoErrorHandler &, std::size_t);
+ void SetPosition(std::int64_t, IoErrorHandler &); // zero-based
void BeginSequentialVariableUnformattedInputRecord(IoErrorHandler &);
void BeginVariableFormattedInputRecord(IoErrorHandler &);
void BackspaceFixedRecord(IoErrorHandler &);
More information about the flang-commits
mailing list