diff options
author | Peter Klausler <pklausler@nvidia.com> | 2022-02-18 04:22:09 +0300 |
---|---|---|
committer | Peter Klausler <pklausler@nvidia.com> | 2022-03-02 23:38:11 +0300 |
commit | 507f7317a0db6e58f170829ec6a10e380450ca47 (patch) | |
tree | 921530ecd9f9ee31d50dc25fb40254c956c11861 /flang | |
parent | 8d7a833eed1a530c260882ffc346a6711cfe96af (diff) |
[flang] Catch READ/WRITE on direct-access file without REC=
A data transfer statement must have REC= in its control list
if (and only if) the unit was opened with ACCESS='DIRECT'.
The runtime wasn't catching this error, but was just silently
advancing to the next record as if the access were sequential.
Differential Revision: https://reviews.llvm.org/D120838
Diffstat (limited to 'flang')
-rw-r--r-- | flang/runtime/unit.cpp | 17 | ||||
-rw-r--r-- | flang/runtime/unit.h | 3 |
2 files changed, 19 insertions, 1 deletions
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index 971909b74e76..6e6db7859278 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -310,6 +310,7 @@ bool ExternalFileUnit::Emit(const char *data, std::size_t bytes, handler.SignalError(IostatWriteAfterEndfile); return false; } + CheckDirectAccess(handler); WriteFrame(frameOffsetInFile_, recordOffsetInFrame_ + furthestAfter, handler); if (positionInRecord > furthestPositionInRecord) { std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord, ' ', @@ -432,7 +433,7 @@ bool ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) { if (!beganReadingRecord_) { beganReadingRecord_ = true; if (access == Access::Direct) { - RUNTIME_CHECK(handler, openRecl); + CheckDirectAccess(handler); auto need{static_cast<std::size_t>(recordOffsetInFrame_ + *openRecl)}; auto got{ReadFrame(frameOffsetInFile_, need, handler)}; if (got >= need) { @@ -654,6 +655,9 @@ void ExternalFileUnit::SetPosition(std::int64_t pos, IoErrorHandler &handler) { DoImpliedEndfile(handler); frameOffsetInFile_ = pos; recordOffsetInFrame_ = 0; + if (access == Access::Direct) { + directAccessRecWasSet_ = true; + } BeginRecord(); } @@ -846,6 +850,17 @@ void ExternalFileUnit::CommitWrites() { BeginRecord(); } +bool ExternalFileUnit::CheckDirectAccess(IoErrorHandler &handler) { + if (access == Access::Direct) { + RUNTIME_CHECK(handler, openRecl); + if (!directAccessRecWasSet_) { + handler.SignalError("No REC= was specified for a data transfer with ACCESS='DIRECT'"); + return false; + } + } + return true; +} + ChildIo &ExternalFileUnit::PushChildIo(IoStatementState &parent) { OwningPtr<ChildIo> current{std::move(child_)}; Terminator &terminator{parent.GetIoErrorHandler()}; diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index c8e65c1f0c4c..7be5e2f387f8 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -71,6 +71,7 @@ public: if constexpr (!std::is_same_v<A, OpenStatementState>) { state.mutableModes() = ConnectionState::modes; } + directAccessRecWasSet_ = false; io_.emplace(state); return *io_; } @@ -112,11 +113,13 @@ private: void DoImpliedEndfile(IoErrorHandler &); void DoEndfile(IoErrorHandler &); void CommitWrites(); + bool CheckDirectAccess(IoErrorHandler &); int unitNumber_{-1}; Direction direction_{Direction::Output}; bool impliedEndfile_{false}; // sequential/stream output has taken place bool beganReadingRecord_{false}; + bool directAccessRecWasSet_{false}; // REC= appeared Lock lock_; |