diff --git a/flang/runtime/io-error.cpp b/flang/runtime/io-error.cpp --- a/flang/runtime/io-error.cpp +++ b/flang/runtime/io-error.cpp @@ -18,16 +18,29 @@ namespace Fortran::runtime::io { void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) { - if (iostatOrErrno == IostatEnd && (flags_ & hasEnd)) { - if (ioStat_ == IostatOk || ioStat_ < IostatEnd) { - ioStat_ = IostatEnd; + // Note that IOMSG= alone without IOSTAT=/END=/EOR=/ERR= does not suffice + // for error recovery (see F'2018 subclause 12.11). + switch (iostatOrErrno) { + case IostatOk: + return; + case IostatEnd: + if (flags_ & (hasIoStat | hasEnd)) { + if (ioStat_ == IostatOk || ioStat_ < IostatEnd) { + ioStat_ = IostatEnd; + } + return; } - } else if (iostatOrErrno == IostatEor && (flags_ & hasEor)) { - if (ioStat_ == IostatOk || ioStat_ < IostatEor) { - ioStat_ = IostatEor; // least priority + break; + case IostatEor: + if (flags_ & (hasIoStat | hasEor)) { + if (ioStat_ == IostatOk || ioStat_ < IostatEor) { + ioStat_ = IostatEor; // least priority + } + return; } - } else if (iostatOrErrno != IostatOk) { - if (flags_ & (hasIoStat | hasIoMsg | hasErr)) { + break; + default: + if (flags_ & (hasIoStat | hasErr)) { if (ioStat_ <= 0) { ioStat_ = iostatOrErrno; // priority over END=/EOR= if (msg && (flags_ & hasIoMsg)) { @@ -39,17 +52,21 @@ va_end(ap); } } - } else if (msg) { - va_list ap; - va_start(ap, msg); - CrashArgs(msg, ap); - va_end(ap); - } else if (const char *errstr{IostatErrorString(iostatOrErrno)}) { - Crash(errstr); - } else { - Crash("I/O error (errno=%d): %s", iostatOrErrno, - std::strerror(iostatOrErrno)); + return; } + break; + } + // I/O error not caught! + if (msg) { + va_list ap; + va_start(ap, msg); + CrashArgs(msg, ap); + va_end(ap); + } else if (const char *errstr{IostatErrorString(iostatOrErrno)}) { + Crash(errstr); + } else { + Crash("I/O error (errno=%d): %s", iostatOrErrno, + std::strerror(iostatOrErrno)); } }