From 514b759a969b8788345f2288fe543507f7d7ba9c Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Sun, 14 Aug 2022 10:29:21 -0700 Subject: [PATCH] [flang][runtime] Catch input error case of missing integer value Formatted input allows for an empty numeric input field, which signifies a zero value, but list-directed and NAMELIST input does not -- apart from the special case of a NAMELIST array. Differential Revision: https://reviews.llvm.org/D132178 --- flang/runtime/edit-input.cpp | 13 +++++++++---- flang/runtime/namelist.cpp | 4 +++- flang/runtime/namelist.h | 7 ++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp index 6417509..7287d2e 100644 --- a/flang/runtime/edit-input.cpp +++ b/flang/runtime/edit-input.cpp @@ -118,7 +118,7 @@ bool EditIntegerInput( RUNTIME_CHECK(io.GetIoErrorHandler(), kind >= 1 && !(kind & (kind - 1))); switch (edit.descriptor) { case DataEdit::ListDirected: - if (IsNamelistName(io)) { + if (IsNamelistNameOrSlash(io)) { return false; } break; @@ -172,6 +172,11 @@ bool EditIntegerInput( value += digit; any = true; } + if (!any && !remaining) { + io.GetIoErrorHandler().SignalError( + "Integer value absent from NAMELIST or list-directed input"); + return false; + } auto maxForKind{common::UnsignedInt128{1} << ((8 * kind) - 1)}; overflow |= value >= maxForKind && (value > maxForKind || !negate); if (overflow) { @@ -527,7 +532,7 @@ template bool EditRealInput(IoStatementState &io, const DataEdit &edit, void *n) { switch (edit.descriptor) { case DataEdit::ListDirected: - if (IsNamelistName(io)) { + if (IsNamelistNameOrSlash(io)) { return false; } return EditCommonRealInput(io, edit, n); @@ -561,7 +566,7 @@ bool EditRealInput(IoStatementState &io, const DataEdit &edit, void *n) { bool EditLogicalInput(IoStatementState &io, const DataEdit &edit, bool &x) { switch (edit.descriptor) { case DataEdit::ListDirected: - if (IsNamelistName(io)) { + if (IsNamelistNameOrSlash(io)) { return false; } break; @@ -650,7 +655,7 @@ static bool EditListDirectedCharacterInput( io.HandleRelativePosition(byteCount); return EditDelimitedCharacterInput(io, x, length, *ch); } - if (IsNamelistName(io) || io.GetConnectionState().IsAtEOF()) { + if (IsNamelistNameOrSlash(io) || io.GetConnectionState().IsAtEOF()) { return false; } // Undelimited list-directed character input: stop at a value separator diff --git a/flang/runtime/namelist.cpp b/flang/runtime/namelist.cpp index 261492b..460a4c9 100644 --- a/flang/runtime/namelist.cpp +++ b/flang/runtime/namelist.cpp @@ -493,7 +493,7 @@ bool IONAME(InputNamelist)(Cookie cookie, const NamelistGroup &group) { return true; } -bool IsNamelistName(IoStatementState &io) { +bool IsNamelistNameOrSlash(IoStatementState &io) { if (auto *listInput{ io.get_if>()}) { if (listInput->inNamelistArray()) { @@ -508,6 +508,8 @@ bool IsNamelistName(IoStatementState &io) { ch = io.GetNextNonBlank(byteCount); // TODO: how to deal with NaN(...) ambiguity? return ch && (*ch == '=' || *ch == '(' || *ch == '%'); + } else { + return *ch == '/'; } } } diff --git a/flang/runtime/namelist.h b/flang/runtime/namelist.h index a7c0912..be40310 100644 --- a/flang/runtime/namelist.h +++ b/flang/runtime/namelist.h @@ -35,10 +35,11 @@ public: const Item *item; // in original declaration order }; -// Look ahead on input for an identifier followed by a '=', '(', or '%' +// Look ahead on input for a '/' or an identifier followed by a '=', '(', or '%' // character; for use in disambiguating a name-like value (e.g. F or T) from a -// NAMELIST group item name. Always false when not reading a NAMELIST. -bool IsNamelistName(IoStatementState &); +// NAMELIST group item name and for coping with short arrays. Always false +// when not reading a NAMELIST. +bool IsNamelistNameOrSlash(IoStatementState &); } // namespace Fortran::runtime::io #endif // FORTRAN_RUNTIME_NAMELIST_H_ -- 2.7.4