forked from OSchip/llvm-project
[flang] Expose error recovery cases in external I/O
Some I/O error situations are current handled with fatal runtime asserts, but should be exposed for user program error recovery. Differential Revision: https://reviews.llvm.org/D122049
This commit is contained in:
parent
240e06dfe7
commit
461b6fe470
|
@ -63,6 +63,9 @@ enum Iostat {
|
|||
IostatFormattedChildOnUnformattedParent,
|
||||
IostatChildInputFromOutputParent,
|
||||
IostatChildOutputToInputParent,
|
||||
IostatShortRead,
|
||||
IostatMissingTerminator,
|
||||
IostatBadUnformattedRecord,
|
||||
};
|
||||
|
||||
const char *IostatErrorString(int);
|
||||
|
|
|
@ -69,6 +69,12 @@ const char *IostatErrorString(int iostat) {
|
|||
return "Child input from output parent unit";
|
||||
case IostatChildOutputToInputParent:
|
||||
return "Child output to input parent unit";
|
||||
case IostatShortRead:
|
||||
return "Read from external unit returned insufficient data";
|
||||
case IostatMissingTerminator:
|
||||
return "Sequential record missing its terminator";
|
||||
case IostatBadUnformattedRecord:
|
||||
return "Erroneous unformatted sequential file record structure";
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -762,10 +762,16 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
|
|||
// checked informatively in NextSequentialVariableUnformattedInputRecord().
|
||||
std::size_t got{
|
||||
ReadFrame(frameOffsetInFile_ - headerBytes, headerBytes, handler)};
|
||||
RUNTIME_CHECK(handler, got >= sizeof footer);
|
||||
if (static_cast<std::int64_t>(got) < headerBytes) {
|
||||
handler.SignalError(IostatShortRead);
|
||||
return;
|
||||
}
|
||||
std::memcpy(&footer, Frame(), sizeof footer);
|
||||
recordLength = footer;
|
||||
RUNTIME_CHECK(handler, frameOffsetInFile_ >= *recordLength + 2 * headerBytes);
|
||||
if (frameOffsetInFile_ < *recordLength + 2 * headerBytes) {
|
||||
handler.SignalError(IostatBadUnformattedRecord);
|
||||
return;
|
||||
}
|
||||
frameOffsetInFile_ -= *recordLength + 2 * headerBytes;
|
||||
if (frameOffsetInFile_ >= headerBytes) {
|
||||
frameOffsetInFile_ -= headerBytes;
|
||||
|
@ -774,9 +780,15 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
|
|||
auto need{static_cast<std::size_t>(
|
||||
recordOffsetInFrame_ + sizeof header + *recordLength)};
|
||||
got = ReadFrame(frameOffsetInFile_, need, handler);
|
||||
RUNTIME_CHECK(handler, got >= need);
|
||||
if (got < need) {
|
||||
handler.SignalError(IostatShortRead);
|
||||
return;
|
||||
}
|
||||
std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
|
||||
RUNTIME_CHECK(handler, header == *recordLength);
|
||||
if (header != *recordLength) {
|
||||
handler.SignalError(IostatBadUnformattedRecord);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// There's no portable memrchr(), unfortunately, and strrchr() would
|
||||
|
@ -816,9 +828,15 @@ void ExternalFileUnit::BackspaceVariableFormattedRecord(
|
|||
frameOffsetInFile_ -= std::min<std::int64_t>(frameOffsetInFile_, 1024);
|
||||
auto need{static_cast<std::size_t>(prevNL + 1 - frameOffsetInFile_)};
|
||||
auto got{ReadFrame(frameOffsetInFile_, need, handler)};
|
||||
RUNTIME_CHECK(handler, got >= need);
|
||||
if (got < need) {
|
||||
handler.SignalError(IostatShortRead);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Frame()[recordOffsetInFrame_ + *recordLength] != '\n') {
|
||||
handler.SignalError(IostatMissingTerminator);
|
||||
return;
|
||||
}
|
||||
RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ + *recordLength] == '\n');
|
||||
if (*recordLength > 0 &&
|
||||
Frame()[recordOffsetInFrame_ + *recordLength - 1] == '\r') {
|
||||
--*recordLength;
|
||||
|
|
Loading…
Reference in New Issue