summaryrefslogtreecommitdiff
path: root/flang/runtime/edit-input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/runtime/edit-input.cpp')
-rw-r--r--flang/runtime/edit-input.cpp26
1 files changed, 19 insertions, 7 deletions
diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index b5725a90ba82..c714a85a336e 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -97,7 +97,6 @@ static RT_API_ATTRS bool EditBOZInput(
return false;
}
if (digits++ == 0) {
- significantBits = 4;
if (ch >= '0' && ch <= '1') {
significantBits = 1;
} else if (ch >= '2' && ch <= '3') {
@@ -125,7 +124,11 @@ static RT_API_ATTRS bool EditBOZInput(
int increment{isHostLittleEndian ? -1 : 1};
auto *data{reinterpret_cast<unsigned char *>(n) +
(isHostLittleEndian ? significantBytes - 1 : bytes - significantBytes)};
- int shift{((digits - 1) * LOG2_BASE) & 7};
+ int bitsAfterFirstDigit{(digits - 1) * LOG2_BASE};
+ int shift{bitsAfterFirstDigit & 7};
+ if (shift + (significantBits - bitsAfterFirstDigit) > 8) {
+ shift = shift - 8; // misaligned octal
+ }
while (digits > 0) {
char32_t ch{*io.NextInField(remaining, edit)};
int digit{0};
@@ -182,8 +185,8 @@ static RT_API_ATTRS char ScanNumericPrefix(IoStatementState &io,
return sign;
}
-RT_API_ATTRS bool EditIntegerInput(
- IoStatementState &io, const DataEdit &edit, void *n, int kind) {
+RT_API_ATTRS bool EditIntegerInput(IoStatementState &io, const DataEdit &edit,
+ void *n, int kind, bool isSigned) {
RUNTIME_CHECK(io.GetIoErrorHandler(), kind >= 1 && !(kind & (kind - 1)));
switch (edit.descriptor) {
case DataEdit::ListDirected:
@@ -211,10 +214,15 @@ RT_API_ATTRS bool EditIntegerInput(
Fortran::common::optional<int> remaining;
Fortran::common::optional<char32_t> next;
char sign{ScanNumericPrefix(io, edit, next, remaining)};
+ if (sign == '-' && !isSigned) {
+ io.GetIoErrorHandler().SignalError("Negative sign in UNSIGNED input field");
+ return false;
+ }
common::UnsignedInt128 value{0};
bool any{!!sign};
bool overflow{false};
const char32_t comma{GetSeparatorChar(edit)};
+ static constexpr auto maxu128{~common::UnsignedInt128{0}};
for (; next; next = io.NextInField(remaining, edit)) {
char32_t ch{*next};
if (ch == ' ' || ch == '\t') {
@@ -248,7 +256,6 @@ RT_API_ATTRS bool EditIntegerInput(
"Bad character '%lc' in INTEGER input field", ch);
return false;
}
- static constexpr auto maxu128{~common::UnsignedInt128{0}};
static constexpr auto maxu128OverTen{maxu128 / 10};
static constexpr int maxLastDigit{
static_cast<int>(maxu128 - (maxu128OverTen * 10))};
@@ -263,8 +270,13 @@ RT_API_ATTRS bool EditIntegerInput(
"Integer value absent from NAMELIST or list-directed input");
return false;
}
- auto maxForKind{common::UnsignedInt128{1} << ((8 * kind) - 1)};
- overflow |= value >= maxForKind && (value > maxForKind || sign != '-');
+ if (isSigned) {
+ auto maxForKind{common::UnsignedInt128{1} << ((8 * kind) - 1)};
+ overflow |= value >= maxForKind && (value > maxForKind || sign != '-');
+ } else {
+ auto maxForKind{maxu128 >> (((16 - kind) * 8) + (isSigned ? 1 : 0))};
+ overflow |= value >= maxForKind;
+ }
if (overflow) {
io.GetIoErrorHandler().SignalError(IostatIntegerInputOverflow,
"Decimal input overflows INTEGER(%d) variable", kind);