Skip to content

Commit

Permalink
[flang][runtime] Support L editing of Logical
Browse files Browse the repository at this point in the history
I tested gfortran and flang(old). https://godbolt.org/z/c89foro4G

Reviewed By: klausler

Differential Revision: https://reviews.llvm.org/D146989
  • Loading branch information
Shao-Ce SUN committed Apr 5, 2023
1 parent 5f17ba1 commit 77d667b
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 1 deletion.
1 change: 1 addition & 0 deletions flang/docs/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions flang/runtime/edit-output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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_);
Expand Down Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion flang/runtime/format-implementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions flang/unittests/Runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_flang_unittest(FlangRuntimeTests
Format.cpp
Inquiry.cpp
ListInputTest.cpp
LogicalFormatTest.cpp
Matmul.cpp
MatmulTranspose.cpp
MiscIntrinsic.cpp
Expand Down
56 changes: 56 additions & 0 deletions flang/unittests/Runtime/LogicalFormatTest.cpp
Original file line number Diff line number Diff line change
@@ -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 << "'";
}

0 comments on commit 77d667b

Please sign in to comment.