[flang] Runtime: Reset list-directed input state for each NAMELIST item
authorpeter klausler <pklausler@nvidia.com>
Wed, 21 Jul 2021 20:07:04 +0000 (13:07 -0700)
committerpeter klausler <pklausler@nvidia.com>
Sat, 24 Jul 2021 01:21:33 +0000 (18:21 -0700)
NAMELIST I/O formatting uses the runtime infrastructure for
list-directed I/O.  List-directed input processing has same state
that requires reinitialization for each successive NAMELIST input
item.  This patch fixes bugs with "null" items and repetition counts
on NAMELIST input items after the first in the group.

Differential Revision: https://reviews.llvm.org/D106694

flang/runtime/io-stmt.h
flang/runtime/namelist.cpp

index 4996435..eeae510 100644 (file)
@@ -217,6 +217,16 @@ public:
   std::optional<DataEdit> GetNextDataEdit(
       IoStatementState &, int maxRepeat = 1);
 
+  // Each NAMELIST input item is a distinct "list-directed"
+  // input statement.  This member function resets this state
+  // so that repetition and null values work correctly for each
+  // successive NAMELIST input item.
+  void ResetForNextNamelistItem() {
+    remaining_ = 0;
+    isFirstItem_ = true;
+    realPart_ = imaginaryPart_ = false;
+  }
+
 private:
   int remaining_{0}; // for "r*" repetition
   std::int64_t initialRecordNumber_;
index 72d669f..7ca8d5c 100644 (file)
@@ -260,6 +260,8 @@ bool IONAME(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
   ConnectionState &connection{io.GetConnectionState()};
   connection.modes.inNamelist = true;
   IoErrorHandler &handler{io.GetIoErrorHandler()};
+  auto *listInput{io.get_if<ListDirectedStatementState<Direction::Input>>()};
+  RUNTIME_CHECK(handler, listInput != nullptr);
   // Check the group header
   std::optional<char32_t> next{io.GetNextNonBlank()};
   if (!next || *next != '&') {
@@ -331,6 +333,7 @@ bool IONAME(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
     }
     io.HandleRelativePosition(1);
     // Read the values into the descriptor
+    listInput->ResetForNextNamelistItem();
     if (!descr::DescriptorIO<Direction::Input>(io, *useDescriptor)) {
       return false;
     }