Skip to content

Commit c078e46

Browse files
committed
[flang][runtime] FLUSH(bad or unconnected unit number) is an error
Some I/O control statements are no-ops when attempted on a bad or unconnected UNIT=, but the standard says that FLUSH is an error in that case. Differential Revision: https://reviews.llvm.org/D128392
1 parent c50e6f5 commit c078e46

File tree

3 files changed

+28
-36
lines changed

3 files changed

+28
-36
lines changed

flang/include/flang/Runtime/iostat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ enum Iostat {
8181
IostatTooManyAsyncOps,
8282
IostatBadBackspaceUnit,
8383
IostatBadUnitNumber,
84+
IostatBadFlushUnit,
8485
};
8586

8687
const char *IostatErrorString(int);

flang/runtime/io-api.cpp

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,18 @@ Cookie IONAME(BeginInternalFormattedInput)(const char *internal,
147147
format, formatLength, scratchArea, scratchBytes, sourceFile, sourceLine);
148148
}
149149

150+
static Cookie NoopUnit(const Terminator &terminator, int unitNumber,
151+
enum Iostat iostat = IostatOk) {
152+
Cookie cookie{&New<NoopStatementState>{terminator}(
153+
terminator.sourceFileName(), terminator.sourceLine(), unitNumber)
154+
.release()
155+
->ioStatementState()};
156+
if (iostat != IostatOk) {
157+
cookie->GetIoErrorHandler().SetPendingError(iostat);
158+
}
159+
return cookie;
160+
}
161+
150162
static ExternalFileUnit *GetOrCreateUnit(int unitNumber, Direction direction,
151163
std::optional<bool> isUnformatted, const Terminator &terminator,
152164
Cookie &errorCookie) {
@@ -156,11 +168,7 @@ static ExternalFileUnit *GetOrCreateUnit(int unitNumber, Direction direction,
156168
errorCookie = nullptr;
157169
return unit;
158170
} else {
159-
errorCookie = &New<NoopStatementState>{terminator}(
160-
terminator.sourceFileName(), terminator.sourceLine(), unitNumber)
161-
.release()
162-
->ioStatementState();
163-
errorCookie->GetIoErrorHandler().SetPendingError(IostatBadUnitNumber);
171+
errorCookie = NoopUnit(terminator, unitNumber, IostatBadUnitNumber);
164172
return nullptr;
165173
}
166174
}
@@ -358,12 +366,7 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
358366
return &unit->BeginIoStatement<OpenStatementState>(
359367
*unit, wasExtant, sourceFile, sourceLine);
360368
} else {
361-
auto &io{
362-
New<NoopStatementState>{terminator}(sourceFile, sourceLine, unitNumber)
363-
.release()
364-
->ioStatementState()};
365-
io.GetIoErrorHandler().SetPendingError(IostatBadUnitNumber);
366-
return &io;
369+
return NoopUnit(terminator, unitNumber, IostatBadUnitNumber);
367370
}
368371
}
369372

@@ -378,7 +381,6 @@ Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
378381

379382
Cookie IONAME(BeginWait)(ExternalUnit unitNumber, AsynchronousId id,
380383
const char *sourceFile, int sourceLine) {
381-
Terminator terminator{sourceFile, sourceLine};
382384
if (ExternalFileUnit * unit{ExternalFileUnit::LookUp(unitNumber)}) {
383385
if (unit->Wait(id)) {
384386
return &unit->BeginIoStatement<ExternalMiscIoStatementState>(
@@ -388,14 +390,9 @@ Cookie IONAME(BeginWait)(ExternalUnit unitNumber, AsynchronousId id,
388390
IostatBadWaitId, unit, sourceFile, sourceLine);
389391
}
390392
} else {
391-
auto &io{
392-
New<NoopStatementState>{terminator}(sourceFile, sourceLine, unitNumber)
393-
.release()
394-
->ioStatementState()};
395-
if (id != 0) {
396-
io.GetIoErrorHandler().SetPendingError(IostatBadWaitUnit);
397-
}
398-
return &io;
393+
Terminator terminator{sourceFile, sourceLine};
394+
return NoopUnit(
395+
terminator, unitNumber, id == 0 ? IostatOk : IostatBadWaitUnit);
399396
}
400397
}
401398
Cookie IONAME(BeginWaitAll)(
@@ -410,10 +407,8 @@ Cookie IONAME(BeginClose)(
410407
*unit, sourceFile, sourceLine);
411408
} else {
412409
// CLOSE(UNIT=bad unit) is just a no-op
413-
Terminator oom{sourceFile, sourceLine};
414-
return &New<NoopStatementState>{oom}(sourceFile, sourceLine, unitNumber)
415-
.release()
416-
->ioStatementState();
410+
Terminator terminator{sourceFile, sourceLine};
411+
return NoopUnit(terminator, unitNumber);
417412
}
418413
}
419414

@@ -423,11 +418,10 @@ Cookie IONAME(BeginFlush)(
423418
return &unit->BeginIoStatement<ExternalMiscIoStatementState>(
424419
*unit, ExternalMiscIoStatementState::Flush, sourceFile, sourceLine);
425420
} else {
426-
// FLUSH(UNIT=unknown) is a no-op
427-
Terminator oom{sourceFile, sourceLine};
428-
return &New<NoopStatementState>{oom}(sourceFile, sourceLine, unitNumber)
429-
.release()
430-
->ioStatementState();
421+
// FLUSH(UNIT=bad unit) is an error; an unconnected unit is a no-op
422+
Terminator terminator{sourceFile, sourceLine};
423+
return NoopUnit(terminator, unitNumber,
424+
unitNumber >= 0 ? IostatOk : IostatBadFlushUnit);
431425
}
432426
}
433427

@@ -438,12 +432,7 @@ Cookie IONAME(BeginBackspace)(
438432
return &unit->BeginIoStatement<ExternalMiscIoStatementState>(
439433
*unit, ExternalMiscIoStatementState::Backspace, sourceFile, sourceLine);
440434
} else {
441-
auto &io{
442-
New<NoopStatementState>{terminator}(sourceFile, sourceLine, unitNumber)
443-
.release()
444-
->ioStatementState()};
445-
io.GetIoErrorHandler().SetPendingError(IostatBadBackspaceUnit);
446-
return &io;
435+
return NoopUnit(terminator, unitNumber, IostatBadBackspaceUnit);
447436
}
448437
}
449438

flang/runtime/iostat.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const char *IostatErrorString(int iostat) {
8787
return "READ/WRITE(ASYNCHRONOUS='YES') on unit without "
8888
"OPEN(ASYNCHRONOUS='YES')";
8989
case IostatBadWaitUnit:
90-
return "WAIT(UNIT=) for a bad unit number";
90+
return "WAIT(UNIT=) for a bad or unconnected unit number";
9191
case IostatBOZInputOverflow:
9292
return "B/O/Z input value overflows variable";
9393
case IostatIntegerInputOverflow:
@@ -107,6 +107,8 @@ const char *IostatErrorString(int iostat) {
107107
return "BACKSPACE on unconnected unit";
108108
case IostatBadUnitNumber:
109109
return "Negative unit number is not allowed";
110+
case IostatBadFlushUnit:
111+
return "FLUSH attempted on a bad or unconnected unit number";
110112
default:
111113
return nullptr;
112114
}

0 commit comments

Comments
 (0)