[flang-commits] [flang] 0a8a572 - [flang][runtime] EOF is recoverable only with END= or IOSTAT=
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Mar 10 10:35:23 PST 2023
Author: Peter Klausler
Date: 2023-03-10T10:35:18-08:00
New Revision: 0a8a572c7ebc027a4e21b3f0073565b0ea2d00c6
URL: https://github.com/llvm/llvm-project/commit/0a8a572c7ebc027a4e21b3f0073565b0ea2d00c6
DIFF: https://github.com/llvm/llvm-project/commit/0a8a572c7ebc027a4e21b3f0073565b0ea2d00c6.diff
LOG: [flang][runtime] EOF is recoverable only with END= or IOSTAT=
The runtime's I/O error handler was not crashing the program on an
end-of-file condition that arises for a data transfer statement with
at least one of ERR= or IOMSG= and none of END= or IOSTAT= control
items. This turns out to be incorrect (per subclause 12.11);
an EOF is recoverable only for END= and/or IOSTAT=, and an
non-advancing end-of-record is recoverable only for EOR= and/or IOSTAT=.
Differential Revision: https://reviews.llvm.org/D145754
Added:
Modified:
flang/runtime/io-error.cpp
Removed:
################################################################################
diff --git a/flang/runtime/io-error.cpp b/flang/runtime/io-error.cpp
index e333f6d75bc4..56e4b24cbe06 100644
--- 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 @@ void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) {
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));
}
}
More information about the flang-commits
mailing list