Skip to content

Commit a55e30b

Browse files
authored
[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 #167569.
1 parent f5f6ca6 commit a55e30b

File tree

5 files changed

+39
-2
lines changed

5 files changed

+39
-2
lines changed

flang-rt/include/flang-rt/runtime/environment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct ExecutionEnvironment {
7373
bool noStopMessage{false}; // NO_STOP_MESSAGE=1 inhibits "Fortran STOP"
7474
bool defaultUTF8{false}; // DEFAULT_UTF8
7575
bool checkPointerDeallocation{true}; // FORT_CHECK_POINTER_DEALLOCATION
76+
bool truncateStream{true}; // FORT_TRUNCATE_STREAM
7677

7778
enum InternalDebugging { WorkQueue = 1 };
7879
int internalDebugging{0}; // FLANG_RT_DEBUG

flang-rt/lib/runtime/environment.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,17 @@ void ExecutionEnvironment::Configure(int ac, const char *av[],
141141
}
142142
}
143143

144+
if (auto *x{std::getenv("FORT_TRUNCATE_STREAM")}) {
145+
char *end;
146+
auto n{std::strtol(x, &end, 10)};
147+
if (n >= 0 && n <= 1 && *end == '\0') {
148+
truncateStream = n != 0;
149+
} else {
150+
std::fprintf(stderr,
151+
"Fortran runtime: FORT_TRUNCATE_STREAM=%s is invalid; ignored\n", x);
152+
}
153+
}
154+
144155
if (auto *x{std::getenv("NO_STOP_MESSAGE")}) {
145156
char *end;
146157
auto n{std::strtol(x, &end, 10)};

flang-rt/lib/runtime/unit.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,8 +783,11 @@ void ExternalFileUnit::DoEndfile(IoErrorHandler &handler) {
783783
frameOffsetInFile_ += recordOffsetInFrame_ + furthestPositionInRecord;
784784
recordOffsetInFrame_ = 0;
785785
FlushOutput(handler);
786-
Truncate(frameOffsetInFile_, handler);
787-
TruncateFrame(frameOffsetInFile_, handler);
786+
if (access != Access::Stream || executionEnvironment.truncateStream) {
787+
// Stream output after positioning truncates with some compilers.
788+
Truncate(frameOffsetInFile_, handler);
789+
TruncateFrame(frameOffsetInFile_, handler);
790+
}
788791
BeginRecord();
789792
impliedEndfile_ = false;
790793
anyWriteSinceLastPositioning_ = false;

flang/docs/Extensions.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,17 @@ print *, [(j,j=1,10)]
946946
This design allows format-driven input with `DT` editing to retain
947947
control over advancement in child input, while otherwise allowing it.
948948

949+
* When output takes place to a file under `ACCESS="STREAM"` after
950+
repositioning it to an earlier position, some compilers will
951+
truncate the file; this behavior is similar to the implicit
952+
`ENDFILE` that takes place under sequential output after a
953+
`BACKSPACE` or `REWIND` statement.
954+
Truncation of streams is not specified in the standard, however,
955+
and it does not take place with all compilers.
956+
In this one, truncation is optional; it occurs by default,
957+
but it can be disabled via `FORT_TRUNCATE_STREAM=0` in the
958+
environment at execution time.
959+
949960
## De Facto Standard Features
950961

951962
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the

flang/docs/RuntimeEnvironment.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,14 @@ The default is 72.
5555
Set `NO_STOP_MESSAGE=1` to disable the extra information about
5656
IEEE floating-point exception flags that the Fortran language
5757
standard requires for `STOP` and `ERROR STOP` statements.
58+
59+
## `FORT_TRUNCATE_STREAM`
60+
61+
Set `FORT_TRUNCATE_STREAM=1` to make output to a formatted unit
62+
with `ACCESS="STREAM"` truncate the file when the unit has been
63+
repositioned via `POS=` to an earlier point in the file.
64+
This behavior is analogous to the implicit writing of an ENDFILE record
65+
when output takes place to a sequential unit after
66+
executing a `BACKSPACE` or `REWIND` statement.
67+
Truncation of a stream-access unit is common to several other
68+
compilers, but it is not mentioned in the standard.

0 commit comments

Comments
 (0)