From d879ac8a6eef683392a02dd0aa62c69d61b894eb Mon Sep 17 00:00:00 2001 From: peter klausler Date: Mon, 3 Aug 2020 11:31:13 -0700 Subject: [PATCH] [flang] Defer "next input record" processing until handlers established External input was detecting "end of file" conditions in BeginExternal...Input() and BeginUnformattedInput() routines before EnableHandlers() could have been called. Defer the "start next record" processing to the input data item handlers (and EndIoStatement() for when there are no data items). Differential Revision: https://reviews.llvm.org/D85161 --- flang/runtime/io-api.cpp | 17 ++++++++--------- flang/runtime/io-stmt.cpp | 19 ++++++++++++++++++- flang/runtime/io-stmt.h | 6 ++++++ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp index 708090a..f36144d 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 b8e7781..a903f70 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 755e594..ddc264a 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 -- 2.7.4