mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 22:36:06 +00:00

This has been done using the following command find libcxx/test -type f -exec perl -pi -e 's|^([^/]+?)((?<!::)size_t)|\1std::\2|' \{} \; And manually removed some false positives in std/depr/depr.c.headers. The `std` module doesn't export `::size_t`, this is a preparation for that module. Reviewed By: ldionne, #libc, EricWF, philnik Differential Revision: https://reviews.llvm.org/D146088
186 lines
6.4 KiB
C++
186 lines
6.4 KiB
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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef TEST_SUPPORT_NASTY_STRING_H
|
|
#define TEST_SUPPORT_NASTY_STRING_H
|
|
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <string>
|
|
#include <type_traits>
|
|
|
|
#include "make_string.h"
|
|
#include "test_macros.h"
|
|
|
|
// This defines a nasty_string similar to nasty_containers. This string's
|
|
// value_type does operator hijacking, which allows us to ensure that the
|
|
// library uses the provided `CharTraits` instead of using operations on
|
|
// the value_type directly.
|
|
|
|
|
|
// When using the code during constant evaluation it relies on
|
|
// P2647R1 Permitting static constexpr variables in constexpr functions
|
|
// This is a C++23 feature, which is not supported by all compilers yet.
|
|
// * GCC >= 13
|
|
// * Clang >= 16
|
|
// * MSVC no support yet
|
|
//
|
|
// TODO After there is proper compiler support use TEST_STD_VER >= 23 instead
|
|
// of this macro in the tests.
|
|
#if TEST_STD_VER < 23 || __cpp_constexpr < 202211L
|
|
# define TEST_HAS_NO_NASTY_STRING
|
|
#endif
|
|
|
|
#ifndef TEST_HAS_NO_NASTY_STRING
|
|
// Make sure the char-like operations in strings do not depend on the char-like type.
|
|
struct nasty_char {
|
|
template <typename T>
|
|
friend auto operator<=>(T, T) = delete;
|
|
|
|
template <typename T>
|
|
friend void operator+(T&&) = delete;
|
|
|
|
template <typename T>
|
|
friend void operator-(T&&) = delete;
|
|
|
|
template <typename T>
|
|
friend void operator&(T&&) = delete;
|
|
|
|
char c;
|
|
};
|
|
|
|
static_assert(std::is_trivial<nasty_char>::value, "");
|
|
static_assert(std::is_standard_layout<nasty_char>::value, "");
|
|
|
|
// These traits are based on the constexpr_traits test class.
|
|
struct nasty_char_traits {
|
|
typedef nasty_char char_type;
|
|
typedef int int_type;
|
|
typedef std::streamoff off_type;
|
|
typedef std::streampos pos_type;
|
|
typedef std::mbstate_t state_type;
|
|
// The comparison_category is omitted so the class will have weak_ordering
|
|
// in C++20. This is intentional.
|
|
|
|
static constexpr void assign(char_type& c1, const char_type& c2) noexcept { c1 = c2; }
|
|
|
|
static constexpr bool eq(char_type c1, char_type c2) noexcept { return c1.c == c2.c; }
|
|
|
|
static constexpr bool lt(char_type c1, char_type c2) noexcept { return c1.c < c2.c; }
|
|
|
|
static constexpr int compare(const char_type* s1, const char_type* s2, std::size_t n);
|
|
static constexpr std::size_t length(const char_type* s);
|
|
static constexpr const char_type* find(const char_type* s, std::size_t n, const char_type& a);
|
|
static constexpr char_type* move(char_type* s1, const char_type* s2, std::size_t n);
|
|
static constexpr char_type* copy(char_type* s1, const char_type* s2, std::size_t n);
|
|
static constexpr char_type* assign(char_type* s, std::size_t n, char_type a);
|
|
|
|
static constexpr int_type not_eof(int_type c) noexcept { return eq_int_type(c, eof()) ? ~eof() : c; }
|
|
|
|
static constexpr char_type to_char_type(int_type c) noexcept { return char_type(c); }
|
|
|
|
static constexpr int_type to_int_type(char_type c) noexcept { return int_type(c.c); }
|
|
|
|
static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept { return c1 == c2; }
|
|
|
|
static constexpr int_type eof() noexcept { return int_type(EOF); }
|
|
};
|
|
|
|
constexpr int nasty_char_traits::compare(const nasty_char* s1, const nasty_char* s2, std::size_t n) {
|
|
for (; n; --n, ++s1, ++s2) {
|
|
if (lt(*s1, *s2))
|
|
return -1;
|
|
if (lt(*s2, *s1))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
constexpr std::size_t nasty_char_traits::length(const nasty_char* s) {
|
|
std::size_t len = 0;
|
|
for (; !eq(*s, nasty_char(0)); ++s)
|
|
++len;
|
|
return len;
|
|
}
|
|
|
|
constexpr const nasty_char* nasty_char_traits::find(const nasty_char* s, std::size_t n, const nasty_char& a) {
|
|
for (; n; --n) {
|
|
if (eq(*s, a))
|
|
return s;
|
|
++s;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
constexpr nasty_char* nasty_char_traits::move(nasty_char* s1, const nasty_char* s2, std::size_t n) {
|
|
nasty_char* 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;
|
|
}
|
|
|
|
constexpr nasty_char* nasty_char_traits::copy(nasty_char* s1, const nasty_char* s2, std::size_t n) {
|
|
if (!std::is_constant_evaluated()) // fails in constexpr because we might be comparing unrelated pointers
|
|
assert(s2 < s1 || s2 >= s1 + n);
|
|
nasty_char* r = s1;
|
|
for (; n; --n, ++s1, ++s2)
|
|
assign(*s1, *s2);
|
|
return r;
|
|
}
|
|
|
|
constexpr nasty_char* nasty_char_traits::assign(nasty_char* s, std::size_t n, nasty_char a) {
|
|
nasty_char* r = s;
|
|
for (; n; --n, ++s)
|
|
assign(*s, a);
|
|
return r;
|
|
}
|
|
|
|
using nasty_string = std::basic_string<nasty_char, nasty_char_traits>;
|
|
|
|
template <std::size_t N>
|
|
struct ToNastyChar {
|
|
constexpr ToNastyChar(const char (&r)[N]) {
|
|
std::transform(r, r + N, std::addressof(text[0]), [](char c) { return nasty_char{c}; });
|
|
}
|
|
nasty_char text[N];
|
|
};
|
|
|
|
template <std::size_t N>
|
|
ToNastyChar(const char (&)[N]) -> ToNastyChar<N>;
|
|
|
|
template <ToNastyChar t>
|
|
constexpr auto to_nasty_char() {
|
|
return t;
|
|
}
|
|
|
|
// A macro like MAKE_CSTRING
|
|
//
|
|
// The difference is this macro can convert the nasty_char too.
|
|
//
|
|
// The lambda is a template, so the 'if constexpr' false branch is not evaluated for the nasty_char.
|
|
# define CONVERT_TO_CSTRING(CHAR, STR) \
|
|
[]<class CharT> { \
|
|
if constexpr (std::is_same_v<CharT, nasty_char>) { \
|
|
static constexpr auto result = to_nasty_char<STR>(); \
|
|
return result.text; \
|
|
} else \
|
|
return MAKE_CSTRING(CharT, STR); \
|
|
}.template operator()<CHAR>() /* */
|
|
#else // TEST_HAS_NO_NASTY_STRING
|
|
# define CONVERT_TO_CSTRING(CharT, STR) MAKE_CSTRING(CharT, STR)
|
|
#endif // TEST_HAS_NO_NASTY_STRING
|
|
|
|
#endif // TEST_SUPPORT_NASTY_STRING_H
|