Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++][test] Fixes constexpr char_traits. #90981

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 40 additions & 17 deletions libcxx/test/support/constexpr_char_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@

#include "test_macros.h"

// Tests whether the pointer p is in the range [first, last).
//
// Precondition: The range [first, last) is a valid range.
//
// Typically the pointers are compared with less than. This is not allowed when
// the pointers belong to different ranges, which is UB. Typically, this is
// benign at run-time, however since UB is not allowed during constant
// evaluation this does not compile. This function does the validation without
// UB.
//
// When p is in the range [first, last) the data can be copied from the
// beginning to the end. Otherwise it needs to be copied from the end to the
// beginning.
template <class CharT>
TEST_CONSTEXPR_CXX14 bool is_pointer_in_range(const CharT* first, const CharT* last, const CharT* p) {
if (first == p) // Needed when n == 0
return true;

for (; first != last; ++first)
if (first == p)
return true;

return false;
}

template <class CharT>
struct constexpr_char_traits
{
Expand Down Expand Up @@ -98,23 +123,21 @@ constexpr_char_traits<CharT>::find(const char_type* s, std::size_t n, const char
}

template <class CharT>
TEST_CONSTEXPR_CXX14 CharT*
constexpr_char_traits<CharT>::move(char_type* s1, const char_type* s2, std::size_t n)
{
char_type* r = s1;
if (s1 < s2)
{
for (; n; --n, ++s1, ++s2)
assign(*s1, *s2);
}
else if (s2 < s1)
{
s1 += n;
s2 += n;
for (; n; --n)
assign(*--s1, *--s2);
}
return r;
TEST_CONSTEXPR_CXX14 CharT* constexpr_char_traits<CharT>::move(char_type* s1, const char_type* s2, std::size_t n) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also add constexpr_char_traits to the PR title?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like short titles, so I made the title more generic and updated the commit message.

if (s1 == s2)
return s1;

char_type* r = s1;
if (is_pointer_in_range(s1, s1 + n, s2)) {
for (; n; --n)
assign(*s1++, *s2++);
} else {
s1 += n;
s2 += n;
for (; n; --n)
assign(*--s1, *--s2);
}
return r;
}

template <class CharT>
Expand Down
12 changes: 8 additions & 4 deletions libcxx/test/support/nasty_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "make_string.h"
#include "test_macros.h"
#include "constexpr_char_traits.h" // is_pointer_in_range

// This defines a nasty_string similar to nasty_containers. This string's
// value_type does operator hijacking, which allows us to ensure that the
Expand Down Expand Up @@ -118,11 +119,14 @@ constexpr const nasty_char* nasty_char_traits::find(const nasty_char* s, std::si
}

constexpr nasty_char* nasty_char_traits::move(nasty_char* s1, const nasty_char* s2, std::size_t n) {
if (s1 == s2)
return s1;

nasty_char* r = s1;
if (s1 < s2) {
for (; n; --n, ++s1, ++s2)
assign(*s1, *s2);
} else if (s2 < s1) {
if (is_pointer_in_range(s1, s1 + n, s2)) {
for (; n; --n)
assign(*s1++, *s2++);
} else {
s1 += n;
s2 += n;
for (; n; --n)
Expand Down
Loading