[flang-commits] [flang] e24f0ac - [flang] Allow record advancement in external formatted sequential READ

peter klausler via flang-commits flang-commits at lists.llvm.org
Wed Sep 30 17:17:23 PDT 2020


Author: peter klausler
Date: 2020-09-30T17:16:55-07:00
New Revision: e24f0ac7a389fcb5c2f5295e717d9f7d3fcd4cea

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

LOG: [flang] Allow record advancement in external formatted sequential READ

The '/' control edit descriptor causes a runtime crash for an
external formatted sequential READ because the AdvanceRecord()
member function for external units implemented only the tasks
to finish reading the current record.  Split those out into
a new FinishReadingRecord() member function, call that instead
from EndIoStatement(), and change AdvanceRecord() to both
finish reading the current record and to begin reading the next
one.

Differential revision: https://reviews.llvm.org/D88607

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index 9bf0284358b9..2a7d552dacd8 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -236,11 +236,13 @@ int NoUnitIoStatementState::EndIoStatement() {
 template <Direction DIR> int ExternalIoStatementState<DIR>::EndIoStatement() {
   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) {
+    if (!unit().nonAdvancing) {
+      FinishReadingRecord();
+    }
+  } else {
+    if (!unit().nonAdvancing) {
+      unit().AdvanceRecord(*this);
+    }
     unit().FlushIfTerminal(*this);
   }
   return ExternalIoStatementBase::EndIoStatement();
@@ -315,10 +317,20 @@ void ExternalIoStatementState<DIR>::HandleRelativePosition(std::int64_t n) {
 template <Direction DIR>
 void ExternalIoStatementState<DIR>::BeginReadingRecord() {
   if constexpr (DIR == Direction::Input) {
-    if (!beganReading_) {
-      beganReading_ = true;
-      unit().BeginReadingRecord(*this);
-    }
+    unit().BeginReadingRecord(*this);
+  } else {
+    Crash("ExternalIoStatementState<Direction::Output>::BeginReadingRecord() "
+          "called");
+  }
+}
+
+template <Direction DIR>
+void ExternalIoStatementState<DIR>::FinishReadingRecord() {
+  if constexpr (DIR == Direction::Input) {
+    unit().FinishReadingRecord(*this);
+  } else {
+    Crash("ExternalIoStatementState<Direction::Output>::FinishReadingRecord() "
+          "called");
   }
 }
 

diff  --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 9e68deab2e64..3c82dc8b1b0a 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -65,6 +65,7 @@ class IoStatementState {
   ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit
   MutableModes &mutableModes();
   void BeginReadingRecord();
+  void FinishReadingRecord();
   bool Inquire(InquiryKeywordHash, char *, std::size_t);
   bool Inquire(InquiryKeywordHash, bool &);
   bool Inquire(InquiryKeywordHash, std::int64_t, bool &); // PENDING=
@@ -123,7 +124,7 @@ struct IoStatementBase : public DefaultFormatControlCallbacks {
   std::optional<DataEdit> GetNextDataEdit(IoStatementState &, int = 1);
   ExternalFileUnit *GetExternalFileUnit() const { return nullptr; }
   void BeginReadingRecord() {}
-
+  void FinishReadingRecord() {}
   bool Inquire(InquiryKeywordHash, char *, std::size_t);
   bool Inquire(InquiryKeywordHash, bool &);
   bool Inquire(InquiryKeywordHash, std::int64_t, bool &);
@@ -269,9 +270,7 @@ class ExternalIoStatementState : public ExternalIoStatementBase,
   void HandleRelativePosition(std::int64_t);
   void HandleAbsolutePosition(std::int64_t);
   void BeginReadingRecord();
-
-private:
-  bool beganReading_{false};
+  void FinishReadingRecord();
 };
 
 template <Direction DIR, typename CHAR>

diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index be36666f66e4..8170fbc696c2 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -349,6 +349,10 @@ void ExternalFileUnit::SetLeftTabLimit() {
 
 void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
   RUNTIME_CHECK(handler, direction_ == Direction::Input);
+  if (beganReadingRecord_) {
+    return;
+  }
+  beganReadingRecord_ = true;
   if (access == Access::Sequential) {
     if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) {
       handler.SignalEnd();
@@ -367,28 +371,37 @@ void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
   }
 }
 
+void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
+  RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_);
+  beganReadingRecord_ = false;
+  if (access == Access::Sequential) {
+    RUNTIME_CHECK(handler, recordLength.has_value());
+    if (isFixedRecordLength) {
+      frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+      recordOffsetInFrame_ = 0;
+    } else if (isUnformatted) {
+      // Retain footer in frame for more efficient BACKSPACE
+      frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+      recordOffsetInFrame_ = sizeof(std::uint32_t);
+      recordLength.reset();
+    } else { // formatted
+      if (Frame()[recordOffsetInFrame_ + *recordLength] == '\r') {
+        ++recordOffsetInFrame_;
+      }
+      recordOffsetInFrame_ += *recordLength + 1;
+      RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ - 1] == '\n');
+      recordLength.reset();
+    }
+  }
+  ++currentRecordNumber;
+  BeginRecord();
+}
+
 bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
   bool ok{true};
   if (direction_ == Direction::Input) {
-    if (access == Access::Sequential) {
-      RUNTIME_CHECK(handler, recordLength.has_value());
-      if (isFixedRecordLength) {
-        frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
-        recordOffsetInFrame_ = 0;
-      } else if (isUnformatted) {
-        // Retain footer in frame for more efficient BACKSPACE
-        frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
-        recordOffsetInFrame_ = sizeof(std::uint32_t);
-        recordLength.reset();
-      } else { // formatted
-        if (Frame()[recordOffsetInFrame_ + *recordLength] == '\r') {
-          ++recordOffsetInFrame_;
-        }
-        recordOffsetInFrame_ += *recordLength + 1;
-        RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ - 1] == '\n');
-        recordLength.reset();
-      }
-    }
+    FinishReadingRecord(handler);
+    BeginReadingRecord(handler);
   } else { // Direction::Output
     if (!isUnformatted) {
       if (isFixedRecordLength && recordLength) {
@@ -406,9 +419,9 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
         recordOffsetInFrame_ + recordLength.value_or(furthestPositionInRecord);
     recordOffsetInFrame_ = 0;
     impliedEndfile_ = true;
+    ++currentRecordNumber;
+    BeginRecord();
   }
-  ++currentRecordNumber;
-  BeginRecord();
   return ok;
 }
 

diff  --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index 9d66d962bc56..644ca4ad63cc 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -78,6 +78,7 @@ class ExternalFileUnit : public ConnectionState,
   std::optional<char32_t> GetCurrentChar(IoErrorHandler &);
   void SetLeftTabLimit();
   void BeginReadingRecord(IoErrorHandler &);
+  void FinishReadingRecord(IoErrorHandler &);
   bool AdvanceRecord(IoErrorHandler &);
   void BackspaceRecord(IoErrorHandler &);
   void FlushIfTerminal(IoErrorHandler &);
@@ -105,6 +106,7 @@ class ExternalFileUnit : public ConnectionState,
   int unitNumber_{-1};
   Direction direction_{Direction::Output};
   bool impliedEndfile_{false}; // seq. output has taken place
+  bool beganReadingRecord_{false};
 
   Lock lock_;
 


        


More information about the flang-commits mailing list