[flang-commits] [flang] [flang][runtime] Support READ after WRITE w/o positioning (PR #74650)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Dec 8 14:55:04 PST 2023


https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/74650

>From 151a9b80de89c21e8c0b3acc7bcf0a5c0e304974 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Wed, 6 Dec 2023 12:00:01 -0800
Subject: [PATCH] [flang][runtime] Support READ after WRITE w/o positioning

Most Fortran implementations support a READ statement after
a WRITE without repositioning on a sequential unit; it
implies on ENDFILE and then hits an EOF condition.

Fixes llvm-test-suite/Fortran/gfortran/regression/backspace_2.f.
---
 flang/runtime/unit.cpp | 13 +++++++++++--
 flang/runtime/unit.h   |  1 +
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 5fa8565c2f61f..14b85a7500683 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -355,6 +355,7 @@ bool ExternalFileUnit::Emit(const char *data, std::size_t bytes,
   }
   positionInRecord += bytes;
   furthestPositionInRecord = furthestAfter;
+  anyWriteSinceLastPositioning_ = true;
   return true;
 }
 
@@ -451,6 +452,11 @@ bool ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
         HitEndOnRead(handler);
       }
     } else {
+      if (anyWriteSinceLastPositioning_ && access == Access::Sequential) {
+        // Most Fortran implementations allow a READ after a WRITE;
+        // the read then just hits an EOF.
+        DoEndfile(handler);
+      }
       recordLength.reset();
       if (IsAtEOF()) {
         handler.SignalEnd();
@@ -595,8 +601,8 @@ void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {
     if (IsAfterEndfile()) {
       // BACKSPACE after explicit ENDFILE
       currentRecordNumber = *endfileRecordNumber;
-    } else if (leftTabLimit) {
-      // BACKSPACE after non-advancing I/O
+    } else if (leftTabLimit && direction_ == Direction::Input) {
+      // BACKSPACE after non-advancing input
       leftTabLimit.reset();
     } else {
       DoImpliedEndfile(handler);
@@ -615,6 +621,7 @@ void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {
       }
     }
     BeginRecord();
+    anyWriteSinceLastPositioning_ = false;
   }
 }
 
@@ -667,6 +674,7 @@ void ExternalFileUnit::Rewind(IoErrorHandler &handler) {
     SetPosition(0, handler);
     currentRecordNumber = 1;
     leftTabLimit.reset();
+    anyWriteSinceLastPositioning_ = false;
   }
 }
 
@@ -928,6 +936,7 @@ void ExternalFileUnit::DoEndfile(IoErrorHandler &handler) {
   TruncateFrame(frameOffsetInFile_, handler);
   BeginRecord();
   impliedEndfile_ = false;
+  anyWriteSinceLastPositioning_ = false;
 }
 
 void ExternalFileUnit::CommitWrites() {
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index 1ec3013ba82b3..140fda3c4d2a8 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -140,6 +140,7 @@ class ExternalFileUnit : public ConnectionState,
   Direction direction_{Direction::Output};
   bool impliedEndfile_{false}; // sequential/stream output has taken place
   bool beganReadingRecord_{false};
+  bool anyWriteSinceLastPositioning_{false};
   bool directAccessRecWasSet_{false}; // REC= appeared
   // Subtle: The beginning of the frame can't be allowed to advance
   // during a single list-directed READ due to the possibility of a



More information about the flang-commits mailing list