diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp index 708090ac6856..f36144d0c3c4 100644 --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -149,9 +149,6 @@ Cookie BeginExternalListIO( unit.SetDirection(DIR, handler); IoStatementState &io{unit.BeginIoStatement>( unit, sourceFile, sourceLine)}; - if constexpr (DIR == Direction::Input) { - unit.BeginReadingRecord(handler); - } return &io; } @@ -185,9 +182,6 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength, IoStatementState &io{ unit.BeginIoStatement>( unit, format, formatLength, sourceFile, sourceLine)}; - if constexpr (DIR == Direction::Input) { - unit.BeginReadingRecord(handler); - } return &io; } @@ -218,9 +212,7 @@ Cookie BeginUnformattedIO( unit, sourceFile, sourceLine)}; IoErrorHandler handler{terminator}; unit.SetDirection(DIR, handler); - if constexpr (DIR == Direction::Input) { - unit.BeginReadingRecord(handler); - } else { + if constexpr (DIR == Direction::Output) { if (unit.access == Access::Sequential && !unit.isFixedRecordLength) { // Create space for (sub)record header to be completed by // UnformattedIoStatementState::EndIoStatement() @@ -838,6 +830,7 @@ bool IONAME(OutputDescriptor)(Cookie cookie, const Descriptor &) { bool IONAME(InputDescriptor)(Cookie cookie, const Descriptor &) { IoStatementState &io{*cookie}; + io.BeginReadingRecord(); io.GetIoErrorHandler().Crash("InputDescriptor: not yet implemented"); // TODO } @@ -855,6 +848,7 @@ bool IONAME(OutputUnformattedBlock)(Cookie cookie, const char *x, bool IONAME(InputUnformattedBlock)( Cookie cookie, char *x, std::size_t length, std::size_t elementBytes) { IoStatementState &io{*cookie}; + io.BeginReadingRecord(); if (auto *unf{io.get_if>()}) { return unf->Receive(x, length, elementBytes); } @@ -883,6 +877,7 @@ bool IONAME(InputInteger)(Cookie cookie, std::int64_t &n, int kind) { "InputInteger64() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; @@ -922,6 +917,7 @@ static bool InputReal(Cookie cookie, REAL &x) { "InputReal() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; @@ -968,6 +964,7 @@ static bool InputComplex(Cookie cookie, REAL x[2]) { "InputComplex() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); for (int j{0}; j < 2; ++j) { if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { @@ -1012,6 +1009,7 @@ bool IONAME(InputAscii)(Cookie cookie, char *x, std::size_t length) { "InputAscii() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; @@ -1044,6 +1042,7 @@ bool IONAME(InputLogical)(Cookie cookie, bool &truth) { "InputLogical() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index b8e7781f235b..a903f708bc62 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -185,7 +185,10 @@ int NoopCloseStatementState::EndIoStatement() { } template int ExternalIoStatementState::EndIoStatement() { - if (!unit().nonAdvancing) { + if constexpr (DIR == Direction::Input) { + BeginReadingRecord(); // in case of READ with no data items + } + if (!unit().nonAdvancing && GetIoStat() != IostatEnd) { unit().AdvanceRecord(*this); } if constexpr (DIR == Direction::Output) { @@ -260,6 +263,16 @@ void ExternalIoStatementState::HandleRelativePosition(std::int64_t n) { return unit().HandleRelativePosition(n); } +template +void ExternalIoStatementState::BeginReadingRecord() { + if constexpr (DIR == Direction::Input) { + if (!beganReading_) { + beganReading_ = true; + unit().BeginReadingRecord(*this); + } + } +} + template ExternalFormattedIoStatementState::ExternalFormattedIoStatementState( ExternalFileUnit &unit, const CHAR *format, std::size_t formatLength, @@ -315,6 +328,10 @@ MutableModes &IoStatementState::mutableModes() { [](auto &x) -> MutableModes & { return x.get().mutableModes(); }, u_); } +void IoStatementState::BeginReadingRecord() { + std::visit([](auto &x) { return x.get().BeginReadingRecord(); }, u_); +} + IoErrorHandler &IoStatementState::GetIoErrorHandler() const { return std::visit( [](auto &x) -> IoErrorHandler & { diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 755e5946ff3b..ddc264aea360 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -59,6 +59,7 @@ public: IoErrorHandler &GetIoErrorHandler() const; ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit MutableModes &mutableModes(); + void BeginReadingRecord(); // N.B.: this also works with base classes template A *get_if() const { @@ -108,6 +109,7 @@ struct IoStatementBase : public DefaultFormatControlCallbacks { int EndIoStatement(); std::optional GetNextDataEdit(IoStatementState &, int = 1); ExternalFileUnit *GetExternalFileUnit() const { return nullptr; } + void BeginReadingRecord() {} }; struct InputStatementState {}; @@ -247,6 +249,10 @@ public: void BackspaceRecord(); void HandleRelativePosition(std::int64_t); void HandleAbsolutePosition(std::int64_t); + void BeginReadingRecord(); + +private: + bool beganReading_{false}; }; template