[flang-commits] [flang] e81c96d - [flang] Handle END= situations better in runtime input

peter klausler via flang-commits flang-commits at lists.llvm.org
Wed Apr 14 09:34:41 PDT 2021


Author: peter klausler
Date: 2021-04-14T09:34:14-07:00
New Revision: e81c96d6f8b1cc974f9dbdd47ed82be6be81ae0a

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

LOG: [flang] Handle END= situations better in runtime input

Debug the input path for READ statements with END= labels;
don't emit errors when the program can handle them.
BeginReadingRecord() member functions have been made
"bool" for more convenient handling of error cases,
and some code in IoErrorHandler has been cleaned up.

Differential Revision: https://reviews.llvm.org/D100421

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/flang/runtime/descriptor-io.h b/flang/runtime/descriptor-io.h
index 514bcffd19d0d..49476682cd728 100644
--- a/flang/runtime/descriptor-io.h
+++ b/flang/runtime/descriptor-io.h
@@ -220,7 +220,9 @@ static bool DescriptorIO(IoStatementState &io, const Descriptor &descriptor) {
     return false;
   }
   if constexpr (DIR == Direction::Input) {
-    io.BeginReadingRecord();
+    if (!io.BeginReadingRecord()) {
+      return false;
+    }
   }
   if (auto *unf{io.get_if<UnformattedIoStatementState<DIR>>()}) {
     std::size_t elementBytes{descriptor.ElementBytes()};

diff  --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index 57a52bfe6ff05..069e57fdcea36 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -894,6 +894,9 @@ bool IONAME(InputUnformattedBlock)(
     Cookie cookie, char *x, std::size_t length, std::size_t elementBytes) {
   IoStatementState &io{*cookie};
   io.BeginReadingRecord();
+  if (io.GetIoErrorHandler().InError()) {
+    return false;
+  }
   if (auto *unf{io.get_if<UnformattedIoStatementState<Direction::Input>>()}) {
     return unf->Receive(x, length, elementBytes);
   }
@@ -1037,7 +1040,7 @@ bool IONAME(InputLogical)(Cookie cookie, bool &truth) {
 
 void IONAME(GetIoMsg)(Cookie cookie, char *msg, std::size_t length) {
   IoErrorHandler &handler{cookie->GetIoErrorHandler()};
-  if (handler.GetIoStat()) { // leave "msg" alone when no error
+  if (handler.InError()) { // leave "msg" alone when no error
     handler.GetIoMsg(msg, length);
   }
 }

diff  --git a/flang/runtime/io-error.cpp b/flang/runtime/io-error.cpp
index 58696728c48a5..f73272ad6fed7 100644
--- a/flang/runtime/io-error.cpp
+++ b/flang/runtime/io-error.cpp
@@ -17,20 +17,13 @@
 
 namespace Fortran::runtime::io {
 
-void IoErrorHandler::Begin(const char *sourceFileName, int sourceLine) {
-  flags_ = 0;
-  ioStat_ = 0;
-  ioMsg_.reset();
-  SetLocation(sourceFileName, sourceLine);
-}
-
 void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) {
   if (iostatOrErrno == IostatEnd && (flags_ & hasEnd)) {
-    if (!ioStat_ || ioStat_ < IostatEnd) {
+    if (ioStat_ == IostatOk || ioStat_ < IostatEnd) {
       ioStat_ = IostatEnd;
     }
   } else if (iostatOrErrno == IostatEor && (flags_ & hasEor)) {
-    if (!ioStat_ || ioStat_ < IostatEor) {
+    if (!ioStat_ == IostatOk || ioStat_ < IostatEor) {
       ioStat_ = IostatEor; // least priority
     }
   } else if (iostatOrErrno != IostatOk) {

diff  --git a/flang/runtime/io-error.h b/flang/runtime/io-error.h
index 5dd7f5e03d080..e51df9b5be866 100644
--- a/flang/runtime/io-error.h
+++ b/flang/runtime/io-error.h
@@ -27,14 +27,13 @@ class IoErrorHandler : public Terminator {
 public:
   using Terminator::Terminator;
   explicit IoErrorHandler(const Terminator &that) : Terminator{that} {}
-  void Begin(const char *sourceFileName, int sourceLine);
   void HasIoStat() { flags_ |= hasIoStat; }
   void HasErrLabel() { flags_ |= hasErr; }
   void HasEndLabel() { flags_ |= hasEnd; }
   void HasEorLabel() { flags_ |= hasEor; }
   void HasIoMsg() { flags_ |= hasIoMsg; }
 
-  bool InError() const { return ioStat_ != 0; }
+  bool InError() const { return ioStat_ != IostatOk; }
 
   void SignalError(int iostatOrErrno, const char *msg, ...);
   void SignalError(int iostatOrErrno);
@@ -58,7 +57,7 @@ class IoErrorHandler : public Terminator {
     hasIoMsg = 16, // IOMSG=
   };
   std::uint8_t flags_{0};
-  int ioStat_{0};
+  int ioStat_{IostatOk};
   OwningPtr<char> ioMsg_;
 };
 

diff  --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index c04013d2d31cb..2fd60903a7da9 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -230,7 +230,7 @@ int NoUnitIoStatementState::EndIoStatement() {
 
 template <Direction DIR> int ExternalIoStatementState<DIR>::EndIoStatement() {
   if constexpr (DIR == Direction::Input) {
-    BeginReadingRecord(); // in case of READ with no data items
+    BeginReadingRecord(); // in case there were no I/O items
     if (!unit().nonAdvancing) {
       FinishReadingRecord();
     }
@@ -310,12 +310,13 @@ void ExternalIoStatementState<DIR>::HandleRelativePosition(std::int64_t n) {
 }
 
 template <Direction DIR>
-void ExternalIoStatementState<DIR>::BeginReadingRecord() {
+bool ExternalIoStatementState<DIR>::BeginReadingRecord() {
   if constexpr (DIR == Direction::Input) {
-    unit().BeginReadingRecord(*this);
+    return unit().BeginReadingRecord(*this);
   } else {
     Crash("ExternalIoStatementState<Direction::Output>::BeginReadingRecord() "
           "called");
+    return false;
   }
 }
 
@@ -384,8 +385,8 @@ MutableModes &IoStatementState::mutableModes() {
       [](auto &x) -> MutableModes & { return x.get().mutableModes(); }, u_);
 }
 
-void IoStatementState::BeginReadingRecord() {
-  std::visit([](auto &x) { return x.get().BeginReadingRecord(); }, u_);
+bool IoStatementState::BeginReadingRecord() {
+  return std::visit([](auto &x) { return x.get().BeginReadingRecord(); }, u_);
 }
 
 IoErrorHandler &IoStatementState::GetIoErrorHandler() const {

diff  --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 686cc0f4cb0ab..000b1ac3238f2 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -71,7 +71,7 @@ class IoStatementState {
   IoErrorHandler &GetIoErrorHandler() const;
   ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit
   MutableModes &mutableModes();
-  void BeginReadingRecord();
+  bool BeginReadingRecord();
   void FinishReadingRecord();
   bool Inquire(InquiryKeywordHash, char *, std::size_t);
   bool Inquire(InquiryKeywordHash, bool &);
@@ -139,7 +139,7 @@ struct IoStatementBase : public DefaultFormatControlCallbacks {
   int EndIoStatement();
   std::optional<DataEdit> GetNextDataEdit(IoStatementState &, int = 1);
   ExternalFileUnit *GetExternalFileUnit() const { return nullptr; }
-  void BeginReadingRecord() {}
+  bool BeginReadingRecord() { return true; }
   void FinishReadingRecord() {}
   bool Inquire(InquiryKeywordHash, char *, std::size_t);
   bool Inquire(InquiryKeywordHash, bool &);
@@ -282,7 +282,7 @@ class ExternalIoStatementState : public ExternalIoStatementBase,
   void BackspaceRecord();
   void HandleRelativePosition(std::int64_t);
   void HandleAbsolutePosition(std::int64_t);
-  void BeginReadingRecord();
+  bool BeginReadingRecord();
   void FinishReadingRecord();
 };
 

diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index d5a9f8e53af48..e84385d4e2670 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -352,34 +352,38 @@ void ExternalFileUnit::SetLeftTabLimit() {
   positionInRecord = furthestPositionInRecord;
 }
 
-void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
+bool 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();
-    } else if (isFixedRecordLength) {
-      RUNTIME_CHECK(handler, recordLength.has_value());
-      auto need{static_cast<std::size_t>(recordOffsetInFrame_ + *recordLength)};
-      auto got{ReadFrame(frameOffsetInFile_, need, handler)};
-      if (got < need) {
+  if (!beganReadingRecord_) {
+    beganReadingRecord_ = true;
+    if (access == Access::Sequential) {
+      if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) {
         handler.SignalEnd();
+      } else if (isFixedRecordLength) {
+        RUNTIME_CHECK(handler, recordLength.has_value());
+        auto need{
+            static_cast<std::size_t>(recordOffsetInFrame_ + *recordLength)};
+        auto got{ReadFrame(frameOffsetInFile_, need, handler)};
+        if (got < need) {
+          handler.SignalEnd();
+        }
+      } else if (isUnformatted) {
+        BeginSequentialVariableUnformattedInputRecord(handler);
+      } else { // formatted
+        BeginSequentialVariableFormattedInputRecord(handler);
       }
-    } else if (isUnformatted) {
-      BeginSequentialVariableUnformattedInputRecord(handler);
-    } else { // formatted
-      BeginSequentialVariableFormattedInputRecord(handler);
     }
   }
+  RUNTIME_CHECK(handler,
+      access != Access::Sequential || recordLength.has_value() ||
+          handler.InError());
+  return !handler.InError();
 }
 
 void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
   RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_);
   beganReadingRecord_ = false;
-  if (handler.GetIoStat() != IostatOk) {
+  if (handler.InError()) {
     // avoid bogus crashes in END/ERR circumstances
   } else if (access == Access::Sequential) {
     RUNTIME_CHECK(handler, recordLength.has_value());
@@ -405,11 +409,11 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
 }
 
 bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
-  bool ok{true};
   if (direction_ == Direction::Input) {
     FinishReadingRecord(handler);
-    BeginReadingRecord(handler);
+    return BeginReadingRecord(handler);
   } else { // Direction::Output
+    bool ok{true};
     if (isFixedRecordLength && recordLength) {
       // Pad remainder of fixed length record
       if (furthestPositionInRecord < *recordLength) {
@@ -445,8 +449,8 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
     impliedEndfile_ = true;
     ++currentRecordNumber;
     BeginRecord();
+    return ok;
   }
-  return ok;
 }
 
 void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {

diff  --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index ff1506c241092..c9db5fceac5bb 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -77,7 +77,7 @@ class ExternalFileUnit : public ConnectionState,
   bool Receive(char *, std::size_t, std::size_t elementBytes, IoErrorHandler &);
   std::optional<char32_t> GetCurrentChar(IoErrorHandler &);
   void SetLeftTabLimit();
-  void BeginReadingRecord(IoErrorHandler &);
+  bool BeginReadingRecord(IoErrorHandler &);
   void FinishReadingRecord(IoErrorHandler &);
   bool AdvanceRecord(IoErrorHandler &);
   void BackspaceRecord(IoErrorHandler &);


        


More information about the flang-commits mailing list