[flang-commits] [flang] f651bbe - [flang] Correct interpretation of RECL=

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Jan 31 12:48:24 PST 2022


Author: Peter Klausler
Date: 2022-01-31T12:48:17-08:00
New Revision: f651bbea0692bef2249c92174796ace873fbe89a

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

LOG: [flang] Correct interpretation of RECL=

When RECL= is set on OPEN(), ensure that it:
  1) enforces a max output record payload size
     (not including header+footer or newline), and
  2) causes padding of short output records only
     for ACCESS='DIRECT'

The previous code was causing some false overrun errors
and applying padding to sequential/stream output files.

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

Added: 
    

Modified: 
    flang/runtime/unit.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index e24e1b9ae64c..363565da6833 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -279,16 +279,23 @@ bool ExternalFileUnit::Emit(const char *data, std::size_t bytes,
       positionInRecord + static_cast<std::int64_t>(bytes))};
   if (openRecl) {
     // Check for fixed-length record overrun, but allow for
-    // the unformatted sequential record header & footer, if any.
-    int extra{access == Access::Sequential && isUnformatted && *isUnformatted
-            ? static_cast<int>(sizeof(std::uint32_t))
-            : 0};
-    if (furthestAfter > 2 * extra + *openRecl) {
+    // sequential record termination.
+    int extra{0};
+    int header{0};
+    if (access == Access::Sequential) {
+      if (isUnformatted.value_or(false)) {
+        // record header + footer
+        header = static_cast<int>(sizeof(std::uint32_t));
+        extra = 2 * header;
+      } else {
+        extra = 1; // newline
+      }
+    }
+    if (furthestAfter > extra + *openRecl) {
       handler.SignalError(IostatRecordWriteOverrun,
           "Attempt to write %zd bytes to position %jd in a fixed-size record "
           "of %jd bytes",
-          bytes,
-          static_cast<std::intmax_t>(positionInRecord - extra /*header*/),
+          bytes, static_cast<std::intmax_t>(positionInRecord - header),
           static_cast<std::intmax_t>(*openRecl));
       return false;
     }
@@ -487,15 +494,17 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
   } else { // Direction::Output
     bool ok{true};
     RUNTIME_CHECK(handler, isUnformatted.has_value());
-    if (openRecl && furthestPositionInRecord < *openRecl) {
-      // Pad remainder of fixed length record
-      WriteFrame(frameOffsetInFile_, recordOffsetInFrame_ + *openRecl, handler);
-      std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
-          isUnformatted.value_or(false) ? 0 : ' ',
-          *openRecl - furthestPositionInRecord);
-      furthestPositionInRecord = *openRecl;
-    }
-    if (!(openRecl && access == Access::Direct)) {
+    if (openRecl && access == Access::Direct) {
+      if (furthestPositionInRecord < *openRecl) {
+        // Pad remainder of fixed length record
+        WriteFrame(
+            frameOffsetInFile_, recordOffsetInFrame_ + *openRecl, handler);
+        std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
+            isUnformatted.value_or(false) ? 0 : ' ',
+            *openRecl - furthestPositionInRecord);
+        furthestPositionInRecord = *openRecl;
+      }
+    } else {
       positionInRecord = furthestPositionInRecord;
       if (isUnformatted.value_or(false)) {
         // Append the length of a sequential unformatted variable-length record


        


More information about the flang-commits mailing list