Skip to content

Commit 0f5c60f

Browse files
committed
[flang] Fix edge-case I/O regressions
A blank field in an input record that exists must be interpreted as a zero value for numeric input editing, but advancing to a next record that doesn't exist should leave an input variable unmodified (and signal END=). On internal output, blank fill the "current record" array element even if nothing has been written to it if it is the only record. Differential Revision: https://reviews.llvm.org/D118720
1 parent b6e048c commit 0f5c60f

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-10
lines changed

flang/runtime/edit-input.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ bool EditIntegerInput(
9999
std::optional<int> remaining;
100100
std::optional<char32_t> next;
101101
bool negate{ScanNumericPrefix(io, edit, next, remaining)};
102-
common::UnsignedInt128 value;
103-
bool any{false};
102+
common::UnsignedInt128 value{0};
103+
bool any{negate};
104104
for (; next; next = io.NextInField(remaining)) {
105105
char32_t ch{*next};
106106
if (ch == ' ' || ch == '\t') {
@@ -122,11 +122,11 @@ bool EditIntegerInput(
122122
value += digit;
123123
any = true;
124124
}
125-
if (any) {
126-
if (negate) {
127-
value = -value;
128-
}
129-
std::memcpy(n, &value, kind);
125+
if (negate) {
126+
value = -value;
127+
}
128+
if (any || !io.GetConnectionState().IsAtEOF()) {
129+
std::memcpy(n, &value, kind); // a blank field means zero
130130
}
131131
return any;
132132
}
@@ -155,7 +155,9 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io,
155155
}
156156
if (next.value_or(' ') == ' ') { // empty/blank field means zero
157157
remaining.reset();
158-
Put('0');
158+
if (!io.GetConnectionState().IsAtEOF()) {
159+
Put('0');
160+
}
159161
return got;
160162
}
161163
char32_t decimal{GetDecimalPoint(edit)};
@@ -524,7 +526,7 @@ static bool EditListDirectedDefaultCharacterInput(
524526
io.HandleRelativePosition(1);
525527
return EditDelimitedCharacterInput(io, x, length, *ch);
526528
}
527-
if (IsNamelistName(io)) {
529+
if (IsNamelistName(io) || io.GetConnectionState().IsAtEOF()) {
528530
return false;
529531
}
530532
// Undelimited list-directed character input: stop at a value separator
@@ -563,6 +565,9 @@ bool EditDefaultCharacterInput(
563565
edit.descriptor);
564566
return false;
565567
}
568+
if (io.GetConnectionState().IsAtEOF()) {
569+
return false;
570+
}
566571
std::optional<int> remaining{length};
567572
if (edit.width && *edit.width > 0) {
568573
remaining = *edit.width;

flang/runtime/internal-unit.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ InternalDescriptorUnit<DIR>::InternalDescriptorUnit(
3939

4040
template <Direction DIR> void InternalDescriptorUnit<DIR>::EndIoStatement() {
4141
if constexpr (DIR == Direction::Output) {
42-
if (furthestPositionInRecord > 0) {
42+
// Clear the remainder of the current record if anything was written
43+
// to it, or if it is the only record.
44+
if (endfileRecordNumber.value_or(-1) == 2 || furthestPositionInRecord > 0) {
4345
BlankFillOutputRecord();
4446
}
4547
}

0 commit comments

Comments
 (0)