aboutsummaryrefslogtreecommitdiff
path: root/flang
diff options
context:
space:
mode:
authorPeter Klausler <pklausler@nvidia.com>2023-07-18 17:05:47 -0700
committerPeter Klausler <pklausler@nvidia.com>2023-07-21 13:13:08 -0700
commitafdbf1b731ef582008e9ad08ecf787b2b6c2dd88 (patch)
tree13730fbce4544cc27f3ecc42be9e92a5a717be18 /flang
parent25d34215bb80459dd328d6f8eb86c43684375d88 (diff)
downloadllvm-afdbf1b731ef582008e9ad08ecf787b2b6c2dd88.zip
llvm-afdbf1b731ef582008e9ad08ecf787b2b6c2dd88.tar.gz
llvm-afdbf1b731ef582008e9ad08ecf787b2b6c2dd88.tar.bz2
[flang][runtime] Detect NEWUNIT= without FILE= or STATUS='SCRATCH'
It is an error to open a new unit with OPEN(NEWUNIT=) and have neither a file name nor a scratch status. Catch it, and report a new error code. Differential Revision: https://reviews.llvm.org/D155967
Diffstat (limited to 'flang')
-rw-r--r--flang/include/flang/Runtime/iostat.h1
-rw-r--r--flang/runtime/io-api.cpp9
-rw-r--r--flang/runtime/io-stmt.cpp6
-rw-r--r--flang/runtime/io-stmt.h7
-rw-r--r--flang/runtime/iostat.cpp2
5 files changed, 18 insertions, 7 deletions
diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h
index ddb82ce..faadaab 100644
--- a/flang/include/flang/Runtime/iostat.h
+++ b/flang/include/flang/Runtime/iostat.h
@@ -83,6 +83,7 @@ enum Iostat {
IostatBadUnitNumber,
IostatBadFlushUnit,
IostatBadOpOnChildUnit,
+ IostatBadNewUnit,
};
const char *IostatErrorString(int);
diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index fe58bbc..2c17f10 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -379,8 +379,8 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
IostatBadOpOnChildUnit, nullptr /* no unit */, sourceFile,
sourceLine);
} else {
- return &unit->BeginIoStatement<OpenStatementState>(
- terminator, *unit, wasExtant, sourceFile, sourceLine);
+ return &unit->BeginIoStatement<OpenStatementState>(terminator, *unit,
+ wasExtant, false /*not NEWUNIT=*/, sourceFile, sourceLine);
}
} else {
return NoopUnit(terminator, unitNumber, IostatBadUnitNumber);
@@ -392,8 +392,9 @@ Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
Terminator terminator{sourceFile, sourceLine};
ExternalFileUnit &unit{
ExternalFileUnit::NewUnit(terminator, false /*not child I/O*/)};
- return &unit.BeginIoStatement<OpenStatementState>(
- terminator, unit, false /*was an existing file*/, sourceFile, sourceLine);
+ return &unit.BeginIoStatement<OpenStatementState>(terminator, unit,
+ false /*was an existing file*/, true /*NEWUNIT=*/, sourceFile,
+ sourceLine);
}
Cookie IONAME(BeginWait)(ExternalUnit unitNumber, AsynchronousId id,
diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index d18f81b..4be7e61 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -240,6 +240,12 @@ void OpenStatementState::CompleteOperation() {
SignalError("FILE= may not appear on OPEN with STATUS='SCRATCH'");
}
}
+ // F'2023 12.5.6.13 - NEWUNIT= requires either FILE= or STATUS='SCRATCH'
+ if (isNewUnit_ && !path_.get() &&
+ status_.value_or(OpenStatus::Unknown) != OpenStatus::Scratch) {
+ SignalError(IostatBadNewUnit);
+ status_ = OpenStatus::Scratch; // error recovery
+ }
if (path_.get() || wasExtant_ ||
(status_ && *status_ == OpenStatus::Scratch)) {
unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs),
diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 33653e6..fa432d0 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -537,10 +537,10 @@ public:
// OPEN
class OpenStatementState : public ExternalIoStatementBase {
public:
- OpenStatementState(ExternalFileUnit &unit, bool wasExtant,
+ OpenStatementState(ExternalFileUnit &unit, bool wasExtant, bool isNewUnit,
const char *sourceFile = nullptr, int sourceLine = 0)
- : ExternalIoStatementBase{unit, sourceFile, sourceLine}, wasExtant_{
- wasExtant} {}
+ : ExternalIoStatementBase{unit, sourceFile, sourceLine},
+ wasExtant_{wasExtant}, isNewUnit_{isNewUnit} {}
bool wasExtant() const { return wasExtant_; }
void set_status(OpenStatus status) { status_ = status; } // STATUS=
void set_path(const char *, std::size_t); // FILE=
@@ -555,6 +555,7 @@ public:
private:
bool wasExtant_;
+ bool isNewUnit_;
std::optional<OpenStatus> status_;
std::optional<Position> position_;
std::optional<Action> action_;
diff --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp
index f34bde2..d786e50 100644
--- a/flang/runtime/iostat.cpp
+++ b/flang/runtime/iostat.cpp
@@ -111,6 +111,8 @@ const char *IostatErrorString(int iostat) {
return "FLUSH attempted on a bad or unconnected unit number";
case IostatBadOpOnChildUnit:
return "Impermissible I/O statement on child I/O unit";
+ case IostatBadNewUnit:
+ return "NEWUNIT= without FILE= or STATUS='SCRATCH'";
default:
return nullptr;
}