diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -188,6 +188,8 @@ if an actual argument acceptable to one could not be passed to the other & vice versa because exactly one is polymorphic or exactly one is unlimited polymorphic). +* External unit 0 is predefined and connected to the standard error output, + and defined as `ERROR_UNIT` in the intrinsic `ISO_FORTRAN_ENV` module. ### Extensions supported when enabled by options diff --git a/flang/module/iso_fortran_env.f90 b/flang/module/iso_fortran_env.f90 --- a/flang/module/iso_fortran_env.f90 +++ b/flang/module/iso_fortran_env.f90 @@ -129,7 +129,7 @@ integer, parameter :: current_team = -1, initial_team = -2, parent_team = -3 integer, parameter :: input_unit = 5, output_unit = 6 - integer, parameter :: error_unit = output_unit + integer, parameter :: error_unit = 0 integer, parameter :: iostat_end = -1, iostat_eor = -2 integer, parameter :: iostat_inquire_internal_unit = -1 diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -21,19 +21,23 @@ // should work without a Fortran main program. static Lock unitMapLock; static UnitMap *unitMap{nullptr}; -static ExternalFileUnit *defaultInput{nullptr}; -static ExternalFileUnit *defaultOutput{nullptr}; +static ExternalFileUnit *defaultInput{nullptr}; // unit 5 +static ExternalFileUnit *defaultOutput{nullptr}; // unit 6 +static ExternalFileUnit *errorOutput{nullptr}; // unit 0 extension void FlushOutputOnCrash(const Terminator &terminator) { - if (!defaultOutput) { + if (!defaultOutput && !errorOutput) { return; } + IoErrorHandler handler{terminator}; + handler.HasIoStat(); // prevent nested crash if flush has error CriticalSection critical{unitMapLock}; if (defaultOutput) { - IoErrorHandler handler{terminator}; - handler.HasIoStat(); // prevent nested crash if flush has error defaultOutput->FlushOutput(handler); } + if (errorOutput) { + errorOutput->FlushOutput(handler); + } } ExternalFileUnit *ExternalFileUnit::LookUp(int unit) { @@ -210,6 +214,7 @@ Terminator terminator{__FILE__, __LINE__}; IoErrorHandler handler{terminator}; UnitMap *newUnitMap{New{terminator}().release()}; + bool wasExtant{false}; ExternalFileUnit &out{newUnitMap->LookUpOrCreate(6, terminator, wasExtant)}; RUNTIME_CHECK(terminator, !wasExtant); @@ -217,12 +222,21 @@ out.SetDirection(Direction::Output, handler); out.isUnformatted = false; defaultOutput = &out; + ExternalFileUnit &in{newUnitMap->LookUpOrCreate(5, terminator, wasExtant)}; RUNTIME_CHECK(terminator, !wasExtant); in.Predefine(0); in.SetDirection(Direction::Input, handler); in.isUnformatted = false; defaultInput = ∈ + + ExternalFileUnit &error{newUnitMap->LookUpOrCreate(0, terminator, wasExtant)}; + RUNTIME_CHECK(terminator, !wasExtant); + error.Predefine(2); + error.SetDirection(Direction::Output, handler); + error.isUnformatted = false; + errorOutput = &error; + // TODO: Set UTF-8 mode from the environment unitMap = newUnitMap; return *unitMap; @@ -235,6 +249,8 @@ FreeMemoryAndNullify(unitMap); } defaultOutput = nullptr; + defaultInput = nullptr; + errorOutput = nullptr; } void ExternalFileUnit::FlushAll(IoErrorHandler &handler) { @@ -627,8 +643,13 @@ void ExternalFileUnit::BeginSequentialVariableFormattedInputRecord( IoErrorHandler &handler) { - if (this == defaultInput && defaultOutput) { - defaultOutput->FlushOutput(handler); + if (this == defaultInput) { + if (defaultOutput) { + defaultOutput->FlushOutput(handler); + } + if (errorOutput) { + errorOutput->FlushOutput(handler); + } } std::size_t length{0}; do {