[flang-commits] [flang] d879ac8 - [flang] Defer "next input record" processing until handlers established

peter klausler via flang-commits flang-commits at lists.llvm.org
Mon Aug 3 16:47:42 PDT 2020


Author: peter klausler
Date: 2020-08-03T16:44:37-07:00
New Revision: d879ac8a6eef683392a02dd0aa62c69d61b894eb

URL: https://github.com/llvm/llvm-project/commit/d879ac8a6eef683392a02dd0aa62c69d61b894eb
DIFF: https://github.com/llvm/llvm-project/commit/d879ac8a6eef683392a02dd0aa62c69d61b894eb.diff

LOG: [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

Added: 
    

Modified: 
    flang/runtime/io-api.cpp
    flang/runtime/io-stmt.cpp
    flang/runtime/io-stmt.h

Removed: 
    


################################################################################
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<ExternalListIoStatementState<DIR>>(
       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<ExternalFormattedIoStatementState<DIR>>(
           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<Direction::Output>::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<UnformattedIoStatementState<Direction::Input>>()}) {
     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 <Direction DIR> int ExternalIoStatementState<DIR>::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<DIR>::HandleRelativePosition(std::int64_t n) {
   return unit().HandleRelativePosition(n);
 }
 
+template <Direction DIR>
+void ExternalIoStatementState<DIR>::BeginReadingRecord() {
+  if constexpr (DIR == Direction::Input) {
+    if (!beganReading_) {
+      beganReading_ = true;
+      unit().BeginReadingRecord(*this);
+    }
+  }
+}
+
 template <Direction DIR, typename CHAR>
 ExternalFormattedIoStatementState<DIR, CHAR>::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 @@ class IoStatementState {
   IoErrorHandler &GetIoErrorHandler() const;
   ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit
   MutableModes &mutableModes();
+  void BeginReadingRecord();
 
   // N.B.: this also works with base classes
   template <typename A> A *get_if() const {
@@ -108,6 +109,7 @@ struct IoStatementBase : public DefaultFormatControlCallbacks {
   int EndIoStatement();
   std::optional<DataEdit> GetNextDataEdit(IoStatementState &, int = 1);
   ExternalFileUnit *GetExternalFileUnit() const { return nullptr; }
+  void BeginReadingRecord() {}
 };
 
 struct InputStatementState {};
@@ -247,6 +249,10 @@ class ExternalIoStatementState : public ExternalIoStatementBase,
   void BackspaceRecord();
   void HandleRelativePosition(std::int64_t);
   void HandleAbsolutePosition(std::int64_t);
+  void BeginReadingRecord();
+
+private:
+  bool beganReading_{false};
 };
 
 template <Direction DIR, typename CHAR>


        


More information about the flang-commits mailing list