[flang-commits] [flang] 77d667b - [flang][runtime] Support L editing of Logical

Shao-Ce SUN via flang-commits flang-commits at lists.llvm.org
Wed Apr 5 10:11:20 PDT 2023


Author: Shao-Ce SUN
Date: 2023-04-06T01:11:12+08:00
New Revision: 77d667b114bee344d1e0459839afe58f4af53089

URL: https://github.com/llvm/llvm-project/commit/77d667b114bee344d1e0459839afe58f4af53089
DIFF: https://github.com/llvm/llvm-project/commit/77d667b114bee344d1e0459839afe58f4af53089.diff

LOG: [flang][runtime] Support L editing of Logical

I tested gfortran and flang(old). https://godbolt.org/z/c89foro4G

Reviewed By: klausler

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

Added: 
    flang/unittests/Runtime/LogicalFormatTest.cpp

Modified: 
    flang/docs/Extensions.md
    flang/runtime/edit-output.cpp
    flang/runtime/format-implementation.h
    flang/unittests/Runtime/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index c49e5c80c0355..fbeada77d6443 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -112,6 +112,7 @@ end
 * Quad precision REAL literals with `Q`
 * `X` prefix/suffix as synonym for `Z` on hexadecimal literals
 * `B`, `O`, `Z`, and `X` accepted as suffixes as well as prefixes
+* Support for using bare `L` in FORMAT statement
 * Triplets allowed in array constructors
 * `%LOC`, `%VAL`, and `%REF`
 * Leading comma allowed before I/O item list

diff  --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp
index 08a75822bacd4..0b31df766087c 100644
--- a/flang/runtime/edit-output.cpp
+++ b/flang/runtime/edit-output.cpp
@@ -139,6 +139,8 @@ bool EditIntegerOutput(IoStatementState &io, const DataEdit &edit,
   case 'Z':
     return EditBOZOutput<4>(
         io, edit, reinterpret_cast<const unsigned char *>(&n), KIND);
+  case 'L':
+    return EditLogicalOutput(io, edit, *reinterpret_cast<const char *>(&n));
   case 'A': // legacy extension
     return EditCharacterOutput(
         io, edit, reinterpret_cast<char *>(&n), sizeof n);
@@ -589,6 +591,8 @@ template <int KIND> bool RealOutputEditing<KIND>::Edit(const DataEdit &edit) {
         common::BitsForBinaryPrecision(common::PrecisionOfRealKind(KIND)) >> 3);
   case 'G':
     return Edit(EditForGOutput(edit));
+  case 'L':
+    return EditLogicalOutput(io_, edit, *reinterpret_cast<const char *>(&x_));
   case 'A': // legacy extension
     return EditCharacterOutput(
         io_, edit, reinterpret_cast<char *>(&x_), sizeof x_);
@@ -712,6 +716,8 @@ bool EditCharacterOutput(IoStatementState &io, const DataEdit &edit,
   case 'Z':
     return EditBOZOutput<4>(io, edit,
         reinterpret_cast<const unsigned char *>(x), sizeof(CHAR) * length);
+  case 'L':
+    return EditLogicalOutput(io, edit, *reinterpret_cast<const char *>(x));
   default:
     io.GetIoErrorHandler().SignalError(IostatErrorInFormat,
         "Data edit descriptor '%c' may not be used with a CHARACTER data item",

diff  --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h
index 89c700eaa4b2d..79063e2f9ebac 100644
--- a/flang/runtime/format-implementation.h
+++ b/flang/runtime/format-implementation.h
@@ -479,7 +479,8 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit(
       }
     }
   }
-  if (edit.descriptor == 'A') { // width is optional for A[w]
+  if (edit.descriptor == 'A' || edit.descriptor == 'L') {
+    // width is optional for A[w] or L[w]
     auto ch{PeekNext()};
     if (ch >= '0' && ch <= '9') {
       edit.width = GetIntField(context);

diff  --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt
index 325eb5433f3a0..bba52706ea2d4 100644
--- a/flang/unittests/Runtime/CMakeLists.txt
+++ b/flang/unittests/Runtime/CMakeLists.txt
@@ -11,6 +11,7 @@ add_flang_unittest(FlangRuntimeTests
   Format.cpp
   Inquiry.cpp
   ListInputTest.cpp
+  LogicalFormatTest.cpp
   Matmul.cpp
   MatmulTranspose.cpp
   MiscIntrinsic.cpp

diff  --git a/flang/unittests/Runtime/LogicalFormatTest.cpp b/flang/unittests/Runtime/LogicalFormatTest.cpp
new file mode 100644
index 0000000000000..a2c19d1e1ca94
--- /dev/null
+++ b/flang/unittests/Runtime/LogicalFormatTest.cpp
@@ -0,0 +1,56 @@
+//===-- flang/unittests/Runtime/LogicalFormatTest.cpp -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CrashHandlerFixture.h"
+#include "flang/Runtime/descriptor.h"
+#include "flang/Runtime/io-api.h"
+#include <algorithm>
+#include <array>
+#include <cstring>
+#include <gtest/gtest.h>
+#include <tuple>
+
+using namespace Fortran::runtime;
+using namespace Fortran::runtime::io;
+
+TEST(IOApiTests, LogicalFormatTest) {
+  static constexpr int bufferSize{29};
+  char buffer[bufferSize];
+
+  // Create format for all types and values to be written
+  const char *format{"(L,L3,I3,L2,L2,I3,L2,A3,L2,L,F4.1,L2)"};
+  auto cookie{IONAME(BeginInternalFormattedOutput)(
+      buffer, bufferSize, format, std::strlen(format))};
+
+  // Write string, integer, and logical values to buffer
+  IONAME(OutputLogical)(cookie, true);
+  IONAME(OutputLogical)(cookie, false);
+  IONAME(OutputInteger64)(cookie, 6);
+  IONAME(OutputInteger32)(cookie, 22);
+  IONAME(OutputInteger32)(cookie, 0);
+  IONAME(OutputInteger32)(cookie, -2);
+  IONAME(OutputCharacter)(cookie, "ABC", 3);
+  IONAME(OutputCharacter)(cookie, "AB", 2);
+  IONAME(OutputReal64)(cookie, 0.0);
+  IONAME(OutputCharacter)(cookie, "", 0);
+  IONAME(OutputReal32)(cookie, 2.3);
+  IONAME(OutputReal32)(cookie, 2.3);
+
+  // Ensure IO succeeded
+  auto status{IONAME(EndIoStatement)(cookie)};
+  ASSERT_EQ(status, 0) << "logical format: '" << format << "' failed, status "
+                       << static_cast<int>(status);
+
+  // Ensure final buffer matches expected string output
+  static const std::string expect{"T  F  6 T F -2 T AB FF 2.3 T"};
+
+  // expect.size() == bufferSize - 1
+  std::string bufferStr = std::string(buffer, bufferSize - 1);
+  ASSERT_TRUE(expect == bufferStr)
+      << "Expected '" << expect << "', got '" << bufferStr << "'";
+}


        


More information about the flang-commits mailing list