[flang-commits] [flang] 341c7c0 - [flang][runtime] Improve Fortran I/O behavior when main program is C/C++
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Aug 18 14:11:02 PDT 2022
Author: Peter Klausler
Date: 2022-08-18T14:10:45-07:00
New Revision: 341c7c05df87394ac23842a0c27889b11a625058
URL: https://github.com/llvm/llvm-project/commit/341c7c05df87394ac23842a0c27889b11a625058
DIFF: https://github.com/llvm/llvm-project/commit/341c7c05df87394ac23842a0c27889b11a625058.diff
LOG: [flang][runtime] Improve Fortran I/O behavior when main program is C/C++
Ensure that I/O buffers are flushed at the end of the program,
and properly detect ttys for predefined units so that Fortran
output is interspersed with output from non-Fortran code.
Fixes https://github.com/llvm/llvm-project/issues/56944
Differential Revision: https://reviews.llvm.org/D132152
Update: fix typo in comment
Added:
Modified:
flang/runtime/file.cpp
flang/runtime/unit.cpp
flang/runtime/unit.h
Removed:
################################################################################
diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp
index 8ff9724762858..b2af0fd7aac3c 100644
--- a/flang/runtime/file.cpp
+++ b/flang/runtime/file.cpp
@@ -134,7 +134,7 @@ void OpenFile::Open(OpenStatus status, std::optional<Action> action,
if (position == Position::Append && !RawSeekToEnd()) {
handler.SignalError(IostatOpenBadAppend);
}
- isTerminal_ = ::isatty(fd_) == 1;
+ isTerminal_ = IsATerminal(fd_) == 1;
mayRead_ = *action != Action::Write;
mayWrite_ = *action != Action::Read;
if (status == OpenStatus::Old || status == OpenStatus::Unknown) {
@@ -163,6 +163,7 @@ void OpenFile::Predefine(int fd) {
knownSize_.reset();
nextId_ = 0;
pending_.reset();
+ isTerminal_ = IsATerminal(fd_) == 1;
mayRead_ = fd == 0;
mayWrite_ = fd != 0;
mayPosition_ = false;
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index ac6311f0408f4..ff7b8938e833d 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -206,42 +206,58 @@ Iostat ExternalFileUnit::SetDirection(Direction direction) {
}
}
-UnitMap &ExternalFileUnit::GetUnitMap() {
- if (unitMap) {
- return *unitMap;
- }
- CriticalSection critical{unitMapLock};
- if (unitMap) {
- return *unitMap;
- }
+UnitMap &ExternalFileUnit::CreateUnitMap() {
Terminator terminator{__FILE__, __LINE__};
IoErrorHandler handler{terminator};
- UnitMap *newUnitMap{New<UnitMap>{terminator}().release()};
+ UnitMap &newUnitMap{*New<UnitMap>{terminator}().release()};
bool wasExtant{false};
- ExternalFileUnit &out{*newUnitMap->LookUpOrCreate(6, terminator, wasExtant)};
+ ExternalFileUnit &out{*newUnitMap.LookUpOrCreate(6, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
out.Predefine(1);
handler.SignalError(out.SetDirection(Direction::Output));
out.isUnformatted = false;
defaultOutput = &out;
- ExternalFileUnit &in{*newUnitMap->LookUpOrCreate(5, terminator, wasExtant)};
+ ExternalFileUnit &in{*newUnitMap.LookUpOrCreate(5, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
in.Predefine(0);
handler.SignalError(in.SetDirection(Direction::Input));
in.isUnformatted = false;
defaultInput = ∈
- ExternalFileUnit &error{
- *newUnitMap->LookUpOrCreate(0, terminator, wasExtant)};
+ ExternalFileUnit &error{*newUnitMap.LookUpOrCreate(0, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
error.Predefine(2);
handler.SignalError(error.SetDirection(Direction::Output));
error.isUnformatted = false;
errorOutput = &error;
- unitMap = newUnitMap;
+ return newUnitMap;
+}
+
+// A back-up atexit() handler for programs that don't terminate with a main
+// program END or a STOP statement or other Fortran-initiated program shutdown,
+// such as programs with a C main() that terminate normally. It flushes all
+// external I/O units. It is registered once the first time that any external
+// I/O is attempted.
+static void CloseAllExternalUnits() {
+ IoErrorHandler handler{"Fortran program termination"};
+ ExternalFileUnit::CloseAll(handler);
+}
+
+UnitMap &ExternalFileUnit::GetUnitMap() {
+ if (unitMap) {
+ return *unitMap;
+ }
+ {
+ CriticalSection critical{unitMapLock};
+ if (unitMap) {
+ return *unitMap;
+ }
+ unitMap = &CreateUnitMap();
+ }
+ std::atexit(CloseAllExternalUnits);
return *unitMap;
}
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index a456a49378947..535f3ba3f6031 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -119,6 +119,7 @@ class ExternalFileUnit : public ConnectionState,
bool Wait(int);
private:
+ static UnitMap &CreateUnitMap();
static UnitMap &GetUnitMap();
const char *FrameNextInput(IoErrorHandler &, std::size_t);
void SetPosition(std::int64_t, IoErrorHandler &); // zero-based
More information about the flang-commits
mailing list