forked from OSchip/llvm-project
[flang] Fix a bug in the character runtime
The number of bytes copied in CopyAndPad should depend on the size of the type being copied, not on its shift value (which in the case of char is 0, leading to no bytes at all being copied). Add unit tests for CharacterMin and CharacterMax, which exercise this code path. Differential Revision: https://reviews.llvm.org/D101355
This commit is contained in:
parent
aaab70407b
commit
5112bd6b6e
|
@ -456,9 +456,9 @@ static void CopyAndPad(
|
|||
to[j] = static_cast<TO>(' ');
|
||||
}
|
||||
} else if (toChars <= fromChars) {
|
||||
std::memcpy(to, from, toChars * shift<TO>);
|
||||
std::memcpy(to, from, toChars * sizeof(TO));
|
||||
} else {
|
||||
std::memcpy(to, from, fromChars * shift<TO>);
|
||||
std::memcpy(to, from, fromChars * sizeof(TO));
|
||||
for (std::size_t j{fromChars}; j < toChars; ++j) {
|
||||
to[j] = static_cast<TO>(' ');
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
// in Fortran.
|
||||
|
||||
#include "../../runtime/character.h"
|
||||
#include "../../runtime/descriptor.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
@ -134,11 +135,79 @@ TYPED_TEST(CharacterComparisonTests, CompareCharacters) {
|
|||
std::memcpy(buf[0], x, xBytes);
|
||||
std::memcpy(buf[1], y, yBytes);
|
||||
ASSERT_EQ(cmp, expect) << "compare '" << x << "'(" << xBytes << ") to '"
|
||||
<< y << "'(" << yBytes << "), got " << cmp
|
||||
<< y << "'(" << yBytes << "'), got " << cmp
|
||||
<< ", should be " << expect << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Test MIN() and MAX()
|
||||
struct ExtremumTestCase {
|
||||
const char *x, *y, *expect;
|
||||
};
|
||||
|
||||
template <typename CHAR>
|
||||
void RunExtremumTests(const char *which,
|
||||
std::function<void(Descriptor &, const Descriptor &, const char *, int)>
|
||||
function,
|
||||
const std::vector<ExtremumTestCase> &testCases) {
|
||||
|
||||
// Helper for creating, allocating and filling up a descriptor with data from
|
||||
// a raw character literal, converted to the CHAR type used by the test.
|
||||
auto CreateDescriptor = [](const char *raw) -> OwningPtr<Descriptor> {
|
||||
std::size_t length{std::strlen(raw)};
|
||||
std::basic_string<CHAR> converted{raw, raw + length};
|
||||
|
||||
OwningPtr<Descriptor> descriptor{Descriptor::Create(
|
||||
sizeof(CHAR), length, nullptr, 0, nullptr, CFI_attribute_allocatable)};
|
||||
if (descriptor->Allocate() != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::copy(
|
||||
converted.begin(), converted.end(), descriptor->OffsetElement<CHAR>());
|
||||
|
||||
return descriptor;
|
||||
};
|
||||
|
||||
for (const auto &t : testCases) {
|
||||
OwningPtr<Descriptor> x = CreateDescriptor(t.x);
|
||||
OwningPtr<Descriptor> y = CreateDescriptor(t.y);
|
||||
|
||||
ASSERT_NE(x, nullptr);
|
||||
ASSERT_TRUE(x->IsAllocated());
|
||||
ASSERT_NE(y, nullptr);
|
||||
ASSERT_TRUE(y->IsAllocated());
|
||||
function(*x, *y, nullptr, 0);
|
||||
|
||||
std::basic_string<CHAR> got{
|
||||
x->OffsetElement<CHAR>(), x->ElementBytes() / sizeof(CHAR)};
|
||||
std::basic_string<CHAR> expect{t.expect, t.expect + std::strlen(t.expect)};
|
||||
EXPECT_EQ(expect, got) << which << "('" << t.x << "','" << t.y
|
||||
<< "') for CHARACTER(kind=" << sizeof(CHAR) << ")";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CHAR> struct ExtremumTests : public ::testing::Test {};
|
||||
TYPED_TEST_CASE(ExtremumTests, CharacterTypes);
|
||||
|
||||
TYPED_TEST(ExtremumTests, MinTests) {
|
||||
static std::vector<ExtremumTestCase> tests{
|
||||
{"a", "z", "a"},
|
||||
{"zaaa", "aa", "aa "},
|
||||
{"aaz", "aaaaa", "aaaaa"},
|
||||
};
|
||||
RunExtremumTests<TypeParam>("MIN", RTNAME(CharacterMin), tests);
|
||||
}
|
||||
|
||||
TYPED_TEST(ExtremumTests, MaxTests) {
|
||||
static std::vector<ExtremumTestCase> tests{
|
||||
{"a", "z", "z"},
|
||||
{"zaa", "aaaaa", "zaa "},
|
||||
{"aaaaa", "aazaa", "aazaa"},
|
||||
};
|
||||
RunExtremumTests<TypeParam>("MAX", RTNAME(CharacterMax), tests);
|
||||
}
|
||||
|
||||
// Test search functions INDEX(), SCAN(), and VERIFY()
|
||||
|
||||
template <typename CHAR>
|
||||
|
|
Loading…
Reference in New Issue