[flang][runtime] Don't always accept a bare exponent letter (#151597)
For more accurate compatibility with other compilers' extensions, accept a bare exponent letter as valid real input to a formatted READ statement only in a fixed-width input field. So it works with (G1.0) editing, but not (G)/(D)/(E)/(F) or list-directed input. Fixes https://github.com/llvm/llvm-project/issues/151465.
This commit is contained in:
parent
aec90f2f27
commit
effa35d240
@ -396,8 +396,9 @@ static RT_API_ATTRS ScannedRealInput ScanRealInput(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (first == radixPointChar || (first >= '0' && first <= '9') ||
|
} else if (first == radixPointChar || (first >= '0' && first <= '9') ||
|
||||||
(bzMode && (first == ' ' || first == '\t')) || first == 'E' ||
|
(bzMode && (first == ' ' || first == '\t')) ||
|
||||||
first == 'D' || first == 'Q') {
|
(remaining.has_value() &&
|
||||||
|
(first == 'D' || first == 'E' || first == 'Q'))) {
|
||||||
if (first == '0') {
|
if (first == '0') {
|
||||||
next = io.NextInField(remaining, edit);
|
next = io.NextInField(remaining, edit);
|
||||||
if (next && (*next == 'x' || *next == 'X')) { // 0X...
|
if (next && (*next == 'x' || *next == 'X')) { // 0X...
|
||||||
@ -462,6 +463,14 @@ static RT_API_ATTRS ScannedRealInput ScanRealInput(
|
|||||||
// optional exponent letter and the exponent value.
|
// optional exponent letter and the exponent value.
|
||||||
io.SkipSpaces(remaining);
|
io.SkipSpaces(remaining);
|
||||||
next = io.NextInField(remaining, edit);
|
next = io.NextInField(remaining, edit);
|
||||||
|
if (!next) {
|
||||||
|
if (remaining.has_value()) {
|
||||||
|
// bare exponent letter accepted in fixed-width field
|
||||||
|
hasGoodExponent = true;
|
||||||
|
} else {
|
||||||
|
return {}; // error
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (next &&
|
if (next &&
|
||||||
|
@ -965,7 +965,10 @@ TEST(IOApiTests, EditDoubleInputValues) {
|
|||||||
{"(RU,E9.1)", " 1.0E-325", 0x1, 0},
|
{"(RU,E9.1)", " 1.0E-325", 0x1, 0},
|
||||||
{"(E9.1)", "-1.0E-325", 0x8000000000000000, 0},
|
{"(E9.1)", "-1.0E-325", 0x8000000000000000, 0},
|
||||||
{"(RD,E9.1)", "-1.0E-325", 0x8000000000000001, 0},
|
{"(RD,E9.1)", "-1.0E-325", 0x8000000000000001, 0},
|
||||||
{"(F7.0))", "+NaN(q)", 0x7ff8000000000000, 0},
|
{"(F7.0)", "+NaN(q)", 0x7ff8000000000000, 0},
|
||||||
|
{"(G)", "D", 0, IostatBadRealInput},
|
||||||
|
{"(G0)", "D", 0, IostatErrorInFormat},
|
||||||
|
{"(G1.0)", "D", 0, 0},
|
||||||
};
|
};
|
||||||
for (auto const &[format, data, want, iostat] : testCases) {
|
for (auto const &[format, data, want, iostat] : testCases) {
|
||||||
auto cookie{IONAME(BeginInternalFormattedInput)(
|
auto cookie{IONAME(BeginInternalFormattedInput)(
|
||||||
@ -988,13 +991,13 @@ TEST(IOApiTests, EditDoubleInputValues) {
|
|||||||
// union value
|
// union value
|
||||||
IONAME(GetIoMsg)(cookie, iomsg, bufferSize - 1);
|
IONAME(GetIoMsg)(cookie, iomsg, bufferSize - 1);
|
||||||
auto status{IONAME(EndIoStatement)(cookie)};
|
auto status{IONAME(EndIoStatement)(cookie)};
|
||||||
ASSERT_EQ(status, iostat)
|
EXPECT_EQ(status, iostat)
|
||||||
<< '\'' << format << "' failed reading '" << data << "', status "
|
<< '\'' << format << "' failed reading '" << data << "', status "
|
||||||
<< static_cast<int>(status) << " != expected " << iostat << " iomsg '"
|
<< static_cast<int>(status) << " != expected " << iostat << " iomsg '"
|
||||||
<< iomsg << "'";
|
<< iomsg << "'";
|
||||||
|
|
||||||
// Ensure raw uint64 value matches expected conversion from double
|
// Ensure raw uint64 value matches expected conversion from double
|
||||||
ASSERT_EQ(u.raw, want) << '\'' << format << "' failed reading '" << data
|
EXPECT_EQ(u.raw, want) << '\'' << format << "' failed reading '" << data
|
||||||
<< "', want " << want << ", got " << u.raw;
|
<< "', want " << want << ", got " << u.raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -479,6 +479,9 @@ end
|
|||||||
* Old-style `PARAMETER pi=3.14` statement without parentheses
|
* Old-style `PARAMETER pi=3.14` statement without parentheses
|
||||||
[-falternative-parameter-statement]
|
[-falternative-parameter-statement]
|
||||||
* `UNSIGNED` type (-funsigned)
|
* `UNSIGNED` type (-funsigned)
|
||||||
|
* Default exponent of zero, e.g. `3.14159E`, on a READ from a
|
||||||
|
fixed-width input field. Includes the case with only an
|
||||||
|
exponent letter for compatibility with other compilers.
|
||||||
|
|
||||||
### Extensions and legacy features deliberately not supported
|
### Extensions and legacy features deliberately not supported
|
||||||
|
|
||||||
@ -492,7 +495,7 @@ end
|
|||||||
* `VIRTUAL` as synonym for `DIMENSION`
|
* `VIRTUAL` as synonym for `DIMENSION`
|
||||||
* `ENCODE` and `DECODE` as synonyms for internal I/O
|
* `ENCODE` and `DECODE` as synonyms for internal I/O
|
||||||
* `IMPLICIT AUTOMATIC`, `IMPLICIT STATIC`
|
* `IMPLICIT AUTOMATIC`, `IMPLICIT STATIC`
|
||||||
* Default exponent of zero, e.g. `3.14159E`
|
* Default exponent of zero, e.g. `3.14159E`, on a literal constant
|
||||||
* Characters in defined operators that are neither letters nor digits
|
* Characters in defined operators that are neither letters nor digits
|
||||||
* `B` suffix on unquoted octal constants
|
* `B` suffix on unquoted octal constants
|
||||||
* `Z` prefix on unquoted hexadecimal constants (dangerous)
|
* `Z` prefix on unquoted hexadecimal constants (dangerous)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user