Skip to content

[flang][runtime] Handle end of internal output correctly #84994

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions flang/runtime/format-implementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,6 @@ template <typename CONTEXT>
int FormatControl<CONTEXT>::GetIntField(
IoErrorHandler &handler, CharType firstCh, bool *hadError) {
CharType ch{firstCh ? firstCh : PeekNext()};
if (ch != '-' && ch != '+' && (ch < '0' || ch > '9')) {
handler.SignalError(IostatErrorInFormat,
"Invalid FORMAT: integer expected at '%c'", static_cast<char>(ch));
if (hadError) {
*hadError = true;
}
return 0;
}
int result{0};
bool negate{ch == '-'};
if (negate || ch == '+') {
if (firstCh) {
Expand All @@ -84,6 +75,15 @@ int FormatControl<CONTEXT>::GetIntField(
}
ch = PeekNext();
}
if (ch < '0' || ch > '9') {
handler.SignalError(IostatErrorInFormat,
"Invalid FORMAT: integer expected at '%c'", static_cast<char>(ch));
if (hadError) {
*hadError = true;
}
return 0;
}
int result{0};
while (ch >= '0' && ch <= '9') {
constexpr int tenth{std::numeric_limits<int>::max() / 10};
if (result > tenth ||
Expand Down Expand Up @@ -246,8 +246,15 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
ch = GetNextChar(context);
}
if (ch == '-' || ch == '+' || (ch >= '0' && ch <= '9')) {
bool hadSign{ch == '-' || ch == '+'};
repeat = GetIntField(context, ch);
ch = GetNextChar(context);
if (hadSign && ch != 'p' && ch != 'P') {
ReportBadFormat(context,
"Invalid FORMAT: signed integer may appear only before 'P",
maybeReversionPoint);
return 0;
}
} else if (ch == '*') {
unlimited = true;
ch = GetNextChar(context);
Expand Down Expand Up @@ -297,11 +304,11 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
return 0;
} else if (ch == ')') {
if (height_ == 1) {
hitEnd_ = true;
if (stop) {
return 0; // end of FORMAT and no data items remain
}
context.AdvanceRecord(); // implied / before rightmost )
hitEnd_ = true;
}
auto restart{stack_[height_ - 1].start};
if (format_[restart] == '(') {
Expand Down
16 changes: 5 additions & 11 deletions flang/runtime/internal-unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,6 @@ InternalDescriptorUnit<DIR>::InternalDescriptorUnit(
endfileRecordNumber = d.Elements() + 1;
}

template <Direction DIR> void InternalDescriptorUnit<DIR>::EndIoStatement() {
if constexpr (DIR == Direction::Output) {
// Clear the remainder of the current record.
auto end{endfileRecordNumber.value_or(0)};
if (currentRecordNumber < end) {
BlankFillOutputRecord();
}
}
}

template <Direction DIR>
bool InternalDescriptorUnit<DIR>::Emit(
const char *data, std::size_t bytes, IoErrorHandler &handler) {
Expand Down Expand Up @@ -109,7 +99,11 @@ std::size_t InternalDescriptorUnit<DIR>::GetNextInputBytes(
template <Direction DIR>
bool InternalDescriptorUnit<DIR>::AdvanceRecord(IoErrorHandler &handler) {
if (currentRecordNumber >= endfileRecordNumber.value_or(0)) {
handler.SignalEnd();
if constexpr (DIR == Direction::Input) {
handler.SignalEnd();
} else {
handler.SignalError(IostatInternalWriteOverrun);
}
return false;
}
if constexpr (DIR == Direction::Output) {
Expand Down
1 change: 0 additions & 1 deletion flang/runtime/internal-unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ template <Direction DIR> class InternalDescriptorUnit : public ConnectionState {
std::conditional_t<DIR == Direction::Input, const char *, char *>;
InternalDescriptorUnit(Scalar, std::size_t chars, int kind);
InternalDescriptorUnit(const Descriptor &, const Terminator &);
void EndIoStatement();

bool Emit(const char *, std::size_t, IoErrorHandler &);
std::size_t GetNextInputBytes(const char *&, IoErrorHandler &);
Expand Down
19 changes: 15 additions & 4 deletions flang/runtime/io-stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,6 @@ template <Direction DIR> void InternalIoStatementState<DIR>::BackspaceRecord() {
}

template <Direction DIR> int InternalIoStatementState<DIR>::EndIoStatement() {
if constexpr (DIR == Direction::Output) {
unit_.EndIoStatement(); // fill
}
auto result{IoStatementBase::EndIoStatement()};
if (free_) {
FreeMemory(this);
Expand Down Expand Up @@ -165,7 +162,8 @@ template <Direction DIR, typename CHAR>
void InternalFormattedIoStatementState<DIR, CHAR>::CompleteOperation() {
if (!this->completedOperation()) {
if constexpr (DIR == Direction::Output) {
format_.Finish(*this); // ignore any remaining input positioning actions
format_.Finish(*this);
unit_.AdvanceRecord(*this);
}
IoStatementBase::CompleteOperation();
}
Expand All @@ -189,8 +187,21 @@ InternalListIoStatementState<DIR>::InternalListIoStatementState(
: InternalIoStatementState<DIR>{d, sourceFile, sourceLine},
ioStatementState_{*this} {}

template <Direction DIR>
void InternalListIoStatementState<DIR>::CompleteOperation() {
if (!this->completedOperation()) {
if constexpr (DIR == Direction::Output) {
if (unit_.furthestPositionInRecord > 0) {
unit_.AdvanceRecord(*this);
}
}
IoStatementBase::CompleteOperation();
}
}

template <Direction DIR>
int InternalListIoStatementState<DIR>::EndIoStatement() {
CompleteOperation();
if constexpr (DIR == Direction::Input) {
if (int status{ListDirectedStatementState<DIR>::EndIoStatement()};
status != IostatOk) {
Expand Down
1 change: 1 addition & 0 deletions flang/runtime/io-stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ class InternalListIoStatementState : public InternalIoStatementState<DIR>,
const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0);
IoStatementState &ioStatementState() { return ioStatementState_; }
using ListDirectedStatementState<DIR>::GetNextDataEdit;
void CompleteOperation();
int EndIoStatement();

private:
Expand Down