[flang-commits] [flang] e29c9d7 - [flang] Fix WRITE after BACKSPACE

peter klausler via flang-commits flang-commits at lists.llvm.org
Thu Oct 1 10:34:13 PDT 2020


Author: peter klausler
Date: 2020-10-01T10:33:31-07:00
New Revision: e29c9d77f128e7ef9b2b5f8f09fb06b01a9dad3a

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

LOG: [flang] Fix WRITE after BACKSPACE

A WRITE to an unformatted sequential variable-length unit after
a BACKSPACE needs to forget its previous knowledge of the length
of the record that's about to be overwritten, and a BACKSPACE
after an ENDFILE or at the start of the file needs to be a no-op.

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

Added: 
    

Modified: 
    flang/runtime/io-api.cpp
    flang/runtime/unit.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index 304c40e871f4..edd338af0fa7 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -235,6 +235,7 @@ Cookie BeginUnformattedIO(
     if (unit.access == Access::Sequential && !unit.isFixedRecordLength) {
       // Create space for (sub)record header to be completed by
       // UnformattedIoStatementState<Direction::Output>::EndIoStatement()
+      unit.recordLength.reset(); // in case of prior BACKSPACE
       io.Emit("\0\0\0\0", 4); // placeholder for record length header
     }
   }

diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index bcb8a478ad59..77b7a74551d8 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -132,16 +132,17 @@ void ExternalFileUnit::OpenUnit(OpenStatus status, std::optional<Action> action,
           static_cast<std::intmax_t>(*totalBytes));
     }
   }
+  endfileRecordNumber.reset();
+  currentRecordNumber = 1;
+  if (totalBytes && recordLength && *recordLength) {
+    endfileRecordNumber = 1 + (*totalBytes / *recordLength);
+  }
   if (position == Position::Append) {
-    if (totalBytes && recordLength && *recordLength) {
-      endfileRecordNumber = 1 + (*totalBytes / *recordLength);
-    } else {
+    if (!endfileRecordNumber) {
       // Fake it so that we can backspace relative from the end
-      endfileRecordNumber = std::numeric_limits<std::int64_t>::max() - 1;
+      endfileRecordNumber = std::numeric_limits<std::int64_t>::max() - 2;
     }
     currentRecordNumber = *endfileRecordNumber;
-  } else {
-    currentRecordNumber = 1;
   }
 }
 
@@ -374,7 +375,9 @@ void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
 void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
   RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_);
   beganReadingRecord_ = false;
-  if (access == Access::Sequential) {
+  if (handler.GetIoStat() != IostatOk) {
+    // avoid bogus crashes in END/ERR circumstances
+  } else if (access == Access::Sequential) {
     RUNTIME_CHECK(handler, recordLength.has_value());
     if (isFixedRecordLength) {
       frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
@@ -430,16 +433,22 @@ void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {
     handler.SignalError(IostatBackspaceNonSequential,
         "BACKSPACE(UNIT=%d) on non-sequential file", unitNumber());
   } else {
-    DoImpliedEndfile(handler);
-    --currentRecordNumber;
-    BeginRecord();
-    if (isFixedRecordLength) {
-      BackspaceFixedRecord(handler);
-    } else if (isUnformatted) {
-      BackspaceVariableUnformattedRecord(handler);
+    if (endfileRecordNumber && currentRecordNumber > *endfileRecordNumber) {
+      // BACKSPACE after ENDFILE
     } else {
-      BackspaceVariableFormattedRecord(handler);
+      DoImpliedEndfile(handler);
+      if (frameOffsetInFile_ + recordOffsetInFrame_ > 0) {
+        --currentRecordNumber;
+        if (isFixedRecordLength) {
+          BackspaceFixedRecord(handler);
+        } else if (isUnformatted) {
+          BackspaceVariableUnformattedRecord(handler);
+        } else {
+          BackspaceVariableFormattedRecord(handler);
+        }
+      }
     }
+    BeginRecord();
   }
 }
 
@@ -456,8 +465,12 @@ void ExternalFileUnit::Endfile(IoErrorHandler &handler) {
   } else if (!mayWrite()) {
     handler.SignalError(IostatEndfileUnwritable,
         "ENDFILE(UNIT=%d) on read-only file", unitNumber());
+  } else if (endfileRecordNumber &&
+      currentRecordNumber > *endfileRecordNumber) {
+    // ENDFILE after ENDFILE
   } else {
     DoEndfile(handler);
+    ++currentRecordNumber;
   }
 }
 
@@ -469,7 +482,6 @@ void ExternalFileUnit::Rewind(IoErrorHandler &handler) {
     DoImpliedEndfile(handler);
     SetPosition(0);
     currentRecordNumber = 1;
-    // TODO: reset endfileRecordNumber?
   }
 }
 


        


More information about the flang-commits mailing list