Index: flang/runtime/character.h =================================================================== --- flang/runtime/character.h +++ flang/runtime/character.h @@ -87,9 +87,9 @@ // Intrinsic functions // The result descriptors below are all established by the runtime. -void RTNAME(Adjustl)(Descriptor &result, const Descriptor &, +void RTNAME(AdjustL)(Descriptor &result, const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0); -void RTNAME(Adjustr)(Descriptor &result, const Descriptor &, +void RTNAME(AdjustR)(Descriptor &result, const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0); std::size_t RTNAME(LenTrim1)(const char *, std::size_t); std::size_t RTNAME(LenTrim2)(const char16_t *, std::size_t); Index: flang/unittests/RuntimeGTest/CharacterTest.cpp =================================================================== --- flang/unittests/RuntimeGTest/CharacterTest.cpp +++ flang/unittests/RuntimeGTest/CharacterTest.cpp @@ -19,6 +19,35 @@ using namespace Fortran::runtime; +using CharacterTypes = ::testing::Types; + +// Helper for creating, allocating and filling up a descriptor with data from +// raw character literals, converted to the CHAR type used by the test. +template +OwningPtr CreateDescriptor(const std::vector &shape, + const std::vector &raw_strings) { + std::size_t length{std::strlen(raw_strings[0])}; + + OwningPtr descriptor{Descriptor::Create(sizeof(CHAR), length, + nullptr, shape.size(), nullptr, CFI_attribute_allocatable)}; + if ((shape.empty() ? descriptor->Allocate() + : descriptor->Allocate( + std::vector(shape.size(), 1).data(), + shape.data())) != 0) { + return nullptr; + } + + std::size_t offset = 0; + for (const char *raw : raw_strings) { + std::basic_string converted{raw, raw + length}; + std::copy(converted.begin(), converted.end(), + descriptor->OffsetElement(offset * length * sizeof(CHAR))); + ++offset; + } + + return descriptor; +} + TEST(CharacterTests, AppendAndPad) { static constexpr int limitMax{8}; static char buffer[limitMax]; @@ -53,6 +82,59 @@ << limit << ", but at offset = " << offset; } +template struct AdjustLRTests : public ::testing::Test {}; +TYPED_TEST_SUITE(AdjustLRTests, CharacterTypes, ); + +struct AdjustLRTestCase { + const char *input, *output; +}; + +template +void RunAdjustLRTest(const char *which, + const std::function &adjust, + const char *inputRaw, const char *outputRaw) { + OwningPtr input{CreateDescriptor({}, {inputRaw})}; + ASSERT_NE(input, nullptr); + ASSERT_TRUE(input->IsAllocated()); + + StaticDescriptor<1> outputStaticDescriptor; + Descriptor &output{outputStaticDescriptor.descriptor()}; + + adjust(output, *input, nullptr, 0); + std::basic_string got{ + output.OffsetElement(), std::strlen(inputRaw)}; + std::basic_string expect{outputRaw, outputRaw + std::strlen(outputRaw)}; + ASSERT_EQ(got, expect) << which << "('" << inputRaw + << "') for CHARACTER(kind=" << sizeof(CHAR) << ")"; +} + +TYPED_TEST(AdjustLRTests, AdjustL) { + static std::vector testcases{ + {" where should the spaces be?", "where should the spaces be? "}, + {" leading and trailing whitespaces ", + "leading and trailing whitespaces "}, + {"shouldn't change", "shouldn't change"}, + }; + + for (const auto &t : testcases) { + RunAdjustLRTest("AdjustL", RTNAME(AdjustL), t.input, t.output); + } +} + +TYPED_TEST(AdjustLRTests, AdjustR) { + static std::vector testcases{ + {"where should the spaces be? ", " where should the spaces be?"}, + {" leading and trailing whitespaces ", + " leading and trailing whitespaces"}, + {"shouldn't change", "shouldn't change"}, + }; + + for (const auto &t : testcases) { + RunAdjustLRTest("AdjustR", RTNAME(AdjustR), t.input, t.output); + } +} + //------------------------------------------------------------------------------ /// Tests and infrastructure for character comparison functions //------------------------------------------------------------------------------ @@ -110,7 +192,6 @@ ComparisonFuncTy characterComparisonFunc; }; -using CharacterTypes = ::testing::Types; TYPED_TEST_SUITE(CharacterComparisonTests, CharacterTypes, ); TYPED_TEST(CharacterComparisonTests, CompareCharacters) { @@ -146,33 +227,6 @@ std::vector x, y, expect; }; -// Helper for creating, allocating and filling up a descriptor with data from -// raw character literals, converted to the CHAR type used by the test. -template -OwningPtr CreateDescriptor(const std::vector &shape, - const std::vector &raw_strings) { - std::size_t length{std::strlen(raw_strings[0])}; - - OwningPtr descriptor{Descriptor::Create(sizeof(CHAR), length, - nullptr, shape.size(), nullptr, CFI_attribute_allocatable)}; - if ((shape.empty() ? descriptor->Allocate() - : descriptor->Allocate( - std::vector(shape.size(), 1).data(), - shape.data())) != 0) { - return nullptr; - } - - std::size_t offset = 0; - for (const char *raw : raw_strings) { - std::basic_string converted{raw, raw + length}; - std::copy(converted.begin(), converted.end(), - descriptor->OffsetElement(offset * length * sizeof(CHAR))); - ++offset; - } - - return descriptor; -} - template void RunExtremumTests(const char *which, std::function