[flang-commits] [flang] a55e30b - [flang][runtime] Control stream truncation via runtime environment (#168415)

via flang-commits flang-commits at lists.llvm.org
Wed Nov 19 08:54:47 PST 2025


Author: Peter Klausler
Date: 2025-11-19T08:54:43-08:00
New Revision: a55e30b12cf90ba2e9c674c94ea3f2b5fa8f2c3b

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

LOG: [flang][runtime] Control stream truncation via runtime environment (#168415)

The ISO Fortran standards don't say whether a WRITE to a formatted
stream unit should truncate the unit if there has been any repositioning
(via POS= control list specifiers) to an earlier point in the stream.
But units with sequential records do truncate on writes after BACKSPACE
and REWIND statements, and many compilers (including this one) truncate
stream units too. Since some compilers don't truncate streams, this
patch adds an environment variable FORT_TRUNCATE_STREAM that can be set
to 0 to disable truncation and ease porting to flang-new of codes that
depend on that behavior.

Fixes https://github.com/llvm/llvm-project/issues/167569.

Added: 
    

Modified: 
    flang-rt/include/flang-rt/runtime/environment.h
    flang-rt/lib/runtime/environment.cpp
    flang-rt/lib/runtime/unit.cpp
    flang/docs/Extensions.md
    flang/docs/RuntimeEnvironment.md

Removed: 
    


################################################################################
diff  --git a/flang-rt/include/flang-rt/runtime/environment.h b/flang-rt/include/flang-rt/runtime/environment.h
index b91cf629509ae..72157fe4418ec 100644
--- a/flang-rt/include/flang-rt/runtime/environment.h
+++ b/flang-rt/include/flang-rt/runtime/environment.h
@@ -73,6 +73,7 @@ struct ExecutionEnvironment {
   bool noStopMessage{false}; // NO_STOP_MESSAGE=1 inhibits "Fortran STOP"
   bool defaultUTF8{false}; // DEFAULT_UTF8
   bool checkPointerDeallocation{true}; // FORT_CHECK_POINTER_DEALLOCATION
+  bool truncateStream{true}; // FORT_TRUNCATE_STREAM
 
   enum InternalDebugging { WorkQueue = 1 };
   int internalDebugging{0}; // FLANG_RT_DEBUG

diff  --git a/flang-rt/lib/runtime/environment.cpp b/flang-rt/lib/runtime/environment.cpp
index 2a2e19f9f17ec..be4f7308ab027 100644
--- a/flang-rt/lib/runtime/environment.cpp
+++ b/flang-rt/lib/runtime/environment.cpp
@@ -141,6 +141,17 @@ void ExecutionEnvironment::Configure(int ac, const char *av[],
     }
   }
 
+  if (auto *x{std::getenv("FORT_TRUNCATE_STREAM")}) {
+    char *end;
+    auto n{std::strtol(x, &end, 10)};
+    if (n >= 0 && n <= 1 && *end == '\0') {
+      truncateStream = n != 0;
+    } else {
+      std::fprintf(stderr,
+          "Fortran runtime: FORT_TRUNCATE_STREAM=%s is invalid; ignored\n", x);
+    }
+  }
+
   if (auto *x{std::getenv("NO_STOP_MESSAGE")}) {
     char *end;
     auto n{std::strtol(x, &end, 10)};

diff  --git a/flang-rt/lib/runtime/unit.cpp b/flang-rt/lib/runtime/unit.cpp
index 549fbeaca05b3..bc98cfdcbe5d2 100644
--- a/flang-rt/lib/runtime/unit.cpp
+++ b/flang-rt/lib/runtime/unit.cpp
@@ -783,8 +783,11 @@ void ExternalFileUnit::DoEndfile(IoErrorHandler &handler) {
   frameOffsetInFile_ += recordOffsetInFrame_ + furthestPositionInRecord;
   recordOffsetInFrame_ = 0;
   FlushOutput(handler);
-  Truncate(frameOffsetInFile_, handler);
-  TruncateFrame(frameOffsetInFile_, handler);
+  if (access != Access::Stream || executionEnvironment.truncateStream) {
+    // Stream output after positioning truncates with some compilers.
+    Truncate(frameOffsetInFile_, handler);
+    TruncateFrame(frameOffsetInFile_, handler);
+  }
   BeginRecord();
   impliedEndfile_ = false;
   anyWriteSinceLastPositioning_ = false;

diff  --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index c9cc02703fbc8..593cd99147515 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -946,6 +946,17 @@ print *, [(j,j=1,10)]
   This design allows format-driven input with `DT` editing to retain
   control over advancement in child input, while otherwise allowing it.
 
+* When output takes place to a file under `ACCESS="STREAM"` after
+  repositioning it to an earlier position, some compilers will
+  truncate the file; this behavior is similar to the implicit
+  `ENDFILE` that takes place under sequential output after a
+  `BACKSPACE` or `REWIND` statement.
+  Truncation of streams is not specified in the standard, however,
+  and it does not take place with all compilers.
+  In this one, truncation is optional; it occurs by default,
+  but it can be disabled via `FORT_TRUNCATE_STREAM=0` in the
+  environment at execution time.
+
 ## De Facto Standard Features
 
 * `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the

diff  --git a/flang/docs/RuntimeEnvironment.md b/flang/docs/RuntimeEnvironment.md
index c7a3dfbb2af1d..ccc401c51e8a3 100644
--- a/flang/docs/RuntimeEnvironment.md
+++ b/flang/docs/RuntimeEnvironment.md
@@ -55,3 +55,14 @@ The default is 72.
 Set `NO_STOP_MESSAGE=1` to disable the extra information about
 IEEE floating-point exception flags that the Fortran language
 standard requires for `STOP` and `ERROR STOP` statements.
+
+## `FORT_TRUNCATE_STREAM`
+
+Set `FORT_TRUNCATE_STREAM=1` to make output to a formatted unit
+with `ACCESS="STREAM"` truncate the file when the unit has been
+repositioned via `POS=` to an earlier point in the file.
+This behavior is analogous to the implicit writing of an ENDFILE record
+when output takes place to a sequential unit after
+executing a `BACKSPACE` or `REWIND` statement.
+Truncation of a stream-access unit is common to several other
+compilers, but it is not mentioned in the standard.


        


More information about the flang-commits mailing list