[flang] When formatting integers for Gw.d/Gw.dEe output, only 'w' matters

Leading zeros should appear only for Iw.m output formatting.
Gw, Gw.d, and Gw.dEe output editing all map to Iw with no ".m"
(Fortran 202X 13.7.5.2.2).

Differential Revision: https://reviews.llvm.org/D159037
This commit is contained in:
Peter Klausler 2023-08-17 11:20:03 -07:00
parent 294f632859
commit 212beb66f8
No known key found for this signature in database
2 changed files with 83 additions and 1 deletions

View File

@ -154,7 +154,8 @@ bool EditIntegerOutput(IoStatementState &io, const DataEdit &edit,
int digits = end - p;
int leadingZeroes{0};
int editWidth{edit.width.value_or(0)};
if (edit.digits && digits <= *edit.digits) { // Iw.m
if (edit.descriptor == 'I' && edit.digits && digits <= *edit.digits) {
// Only Iw.m can produce leading zeroes, not Gw.d (F'202X 13.7.5.2.2)
if (*edit.digits == 0 && n == 0) {
// Iw.0 with zero value: output field must be blank. For I0.0
// and a zero value, emit one blank character.

View File

@ -57,6 +57,22 @@ static bool CompareFormatReal(const char *format, std::uint64_t xInt,
return CompareFormatReal(format, x, expect, got);
}
static bool CompareFormatInteger(
const char *format, std::int64_t x, const char *expect, std::string &got) {
char buffer[800];
auto cookie{IONAME(BeginInternalFormattedOutput)(
buffer, sizeof buffer, format, std::strlen(format))};
EXPECT_TRUE(IONAME(OutputInteger64)(cookie, x));
auto status{IONAME(EndIoStatement)(cookie)};
EXPECT_EQ(status, 0);
got = std::string{buffer, sizeof buffer};
auto lastNonBlank{got.find_last_not_of(" ")};
if (lastNonBlank != std::string::npos) {
got.resize(lastNonBlank + 1);
}
return CompareFormattedStrings(expect, got);
}
struct IOApiTests : CrashHandlerFixture {};
TEST(IOApiTests, HelloWorldOutputTest) {
@ -693,6 +709,71 @@ TEST(IOApiTests, FormatDoubleValues) {
}
}
TEST(IOApiTests, FormatIntegerValues) {
using IntTestCaseTy = std::tuple<const char *, std::int64_t, const char *>;
static const std::vector<IntTestCaseTy> intTestCases{
{"(I4)", 0, " 0"},
{"(I4)", 1, " 1"},
{"(I4)", 9999, "9999"},
{"(SP,I4)", 1, " +1"},
{"(SP,I4)", 9999, "****"},
{"(SP,I4)", 999, "+999"},
{"(I4)", -1, " -1"},
{"(I4)", -9999, "****"},
{"(I4)", -999, "-999"},
{"(I4.2)", 1, " 01"},
{"(I4.2)", -1, " -01"},
{"(I4.2)", 999, " 999"},
{"(I4.4)", 999, "0999"},
{"(I0)", 0, "0"},
{"(I0)", 1, "1"},
{"(I0)", 9999, "9999"},
{"(SP,I0)", 1, "+1"},
{"(SP,I0)", 9999, "+9999"},
{"(SP,I0)", 999, "+999"},
{"(I0)", -1, "-1"},
{"(I0)", -9999, "-9999"},
{"(I0)", -999, "-999"},
{"(I0.2)", 1, "01"},
{"(I0.2)", -1, "-01"},
{"(I0.2)", 999, "999"},
{"(I0.4)", 999, "0999"},
{"(G4)", 0, " 0"},
{"(G4)", 1, " 1"},
{"(G4)", 9999, "9999"},
{"(SP,G4)", 1, " +1"},
{"(SP,G4)", 9999, "****"},
{"(SP,G4)", 999, "+999"},
{"(G4)", -1, " -1"},
{"(G4)", -9999, "****"},
{"(G4)", -999, "-999"},
{"(G4.2)", 1, " 1"},
{"(G4.2)", -1, " -1"},
{"(G4.2)", 999, " 999"},
{"(G4.4)", 999, " 999"},
{"(G0)", 0, "0"},
{"(G0)", 1, "1"},
{"(G0)", 9999, "9999"},
{"(SP,G0)", 1, "+1"},
{"(SP,G0)", 9999, "+9999"},
{"(SP,G0)", 999, "+999"},
{"(G0)", -1, "-1"},
{"(G0)", -9999, "-9999"},
{"(G0)", -999, "-999"},
{"(G0.2)", 1, "1"},
{"(G0.2)", -1, "-1"},
{"(G0.2)", 999, "999"},
{"(G0.4)", 999, "999"},
};
for (auto const &[fmt, value, expect] : intTestCases) {
std::string got;
ASSERT_TRUE(CompareFormatInteger(fmt, value, expect, got))
<< "Failed to format " << fmt << ", expected '" << expect << "', got '"
<< got << "'";
}
}
//------------------------------------------------------------------------------
/// Tests for input formatting real values
//------------------------------------------------------------------------------