Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// <string_view>

// template<class charT, class traits>
// constexpr bool operator<(basic_string_view<charT, traits> lhs, basic_string_view<charT, traits> rhs);
// (plus "sufficient additional overloads" to make implicit conversions work as intended)

#include <string_view>
#include <cassert>
#include <string>

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

template<class T>
struct ConvertibleTo {
T t_;
TEST_CONSTEXPR explicit ConvertibleTo(T t) : t_(t) {}
TEST_CONSTEXPR operator T() const {
return t_;
}
};

template<class SV>
TEST_CONSTEXPR_CXX14 bool test()
{
typedef typename SV::value_type CharT;
typedef typename SV::traits_type Traits;

// Test the behavior of the operator, both with and without implicit conversions.
SV v[] = {
SV(MAKE_CSTRING(CharT, "")),
SV(MAKE_CSTRING(CharT, "abc")),
SV(MAKE_CSTRING(CharT, "abcdef")),
SV(MAKE_CSTRING(CharT, "acb")),
};
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
// See http://eel.is/c++draft/string.view#tab:string.view.comparison.overloads
bool expected = (i < j);
assert((v[i] < v[j]) == expected);
assert((v[i].data() < v[j]) == expected);
assert((v[i] < v[j].data()) == expected);
assert((ConvertibleTo<SV>(v[i]) < v[j]) == expected);
assert((v[i] < ConvertibleTo<SV>(v[j])) == expected);

if (!TEST_IS_CONSTANT_EVALUATED) {
// TODO FIXME: once P0980 "Making std::string constexpr" is implemented
assert((std::basic_string<CharT, Traits>(v[i]) < v[j]) == expected);
assert((v[i] < std::basic_string<CharT, Traits>(v[j])) == expected);
}
}
}

// Test its behavior with embedded null bytes.
SV abc = SV(MAKE_CSTRING(CharT, "abc"));
SV abc0def = SV(MAKE_CSTRING(CharT, "abc\0def"), 7);
SV abcdef = SV(MAKE_CSTRING(CharT, "abcdef"));
assert((abc < abc0def) == true);
assert((abc < abcdef) == true);
assert((abc0def < abc) == false);
assert((abc0def < abcdef) == true);
assert((abcdef < abc) == false);
assert((abcdef < abc0def) == false);

assert((abc.data() < abc0def) == true);
assert((abc0def < abc.data()) == false);

if (!TEST_IS_CONSTANT_EVALUATED) {
// TODO FIXME: once P0980 "Making std::string constexpr" is implemented
assert((std::basic_string<CharT, Traits>(abc) < abc0def) == true);
assert((abc0def < std::basic_string<CharT, Traits>(abc)) == false);
}

return true;
}

int main(int, char**)
{
test<std::string_view>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<std::wstring_view>();
#endif
#if TEST_STD_VER >= 11
test<std::u16string_view>();
test<std::u32string_view>();
#endif
#if TEST_STD_VER > 14
static_assert(test<std::string_view>(), "");
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
static_assert(test<std::wstring_view>(), "");
#endif
static_assert(test<std::u16string_view>(), "");
static_assert(test<std::u32string_view>(), "");
#endif

#if TEST_STD_VER > 11
test<std::basic_string_view<char, constexpr_char_traits<char>>>();
static_assert(test<std::basic_string_view<char, constexpr_char_traits<char>>>(), "");
#endif

#if TEST_STD_VER > 17
test<std::u8string_view>();
static_assert(test<std::u8string_view>());
#endif

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// <string_view>

// template<class charT, class traits>
// constexpr bool operator<=(basic_string_view<charT, traits> lhs, basic_string_view<charT, traits> rhs);
// (plus "sufficient additional overloads" to make implicit conversions work as intended)

#include <string_view>
#include <cassert>
#include <string>

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

template<class T>
struct ConvertibleTo {
T t_;
TEST_CONSTEXPR explicit ConvertibleTo(T t) : t_(t) {}
TEST_CONSTEXPR operator T() const {
return t_;
}
};

template<class SV>
TEST_CONSTEXPR_CXX14 bool test()
{
typedef typename SV::value_type CharT;
typedef typename SV::traits_type Traits;

// Test the behavior of the operator, both with and without implicit conversions.
SV v[] = {
SV(MAKE_CSTRING(CharT, "")),
SV(MAKE_CSTRING(CharT, "abc")),
SV(MAKE_CSTRING(CharT, "abcdef")),
SV(MAKE_CSTRING(CharT, "acb")),
};
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
// See http://eel.is/c++draft/string.view#tab:string.view.comparison.overloads
bool expected = (i <= j);
assert((v[i] <= v[j]) == expected);
assert((v[i].data() <= v[j]) == expected);
assert((v[i] <= v[j].data()) == expected);
assert((ConvertibleTo<SV>(v[i]) <= v[j]) == expected);
assert((v[i] <= ConvertibleTo<SV>(v[j])) == expected);

if (!TEST_IS_CONSTANT_EVALUATED) {
// TODO FIXME: once P0980 "Making std::string constexpr" is implemented
assert((std::basic_string<CharT, Traits>(v[i]) <= v[j]) == expected);
assert((v[i] <= std::basic_string<CharT, Traits>(v[j])) == expected);
}
}
}

// Test its behavior with embedded null bytes.
SV abc = SV(MAKE_CSTRING(CharT, "abc"));
SV abc0def = SV(MAKE_CSTRING(CharT, "abc\0def"), 7);
SV abcdef = SV(MAKE_CSTRING(CharT, "abcdef"));
assert((abc <= abc0def) == true);
assert((abc <= abcdef) == true);
assert((abc0def <= abc) == false);
assert((abc0def <= abcdef) == true);
assert((abcdef <= abc) == false);
assert((abcdef <= abc0def) == false);

assert((abc.data() <= abc0def) == true);
assert((abc0def <= abc.data()) == false);

if (!TEST_IS_CONSTANT_EVALUATED) {
// TODO FIXME: once P0980 "Making std::string constexpr" is implemented
assert((std::basic_string<CharT, Traits>(abc) <= abc0def) == true);
assert((abc0def <= std::basic_string<CharT, Traits>(abc)) == false);
}

return true;
}

int main(int, char**)
{
test<std::string_view>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<std::wstring_view>();
#endif
#if TEST_STD_VER >= 11
test<std::u16string_view>();
test<std::u32string_view>();
#endif
#if TEST_STD_VER > 14
static_assert(test<std::string_view>(), "");
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
static_assert(test<std::wstring_view>(), "");
#endif
static_assert(test<std::u16string_view>(), "");
static_assert(test<std::u32string_view>(), "");
#endif

#if TEST_STD_VER > 11
test<std::basic_string_view<char, constexpr_char_traits<char>>>();
static_assert(test<std::basic_string_view<char, constexpr_char_traits<char>>>(), "");
#endif

#if TEST_STD_VER > 17
test<std::u8string_view>();
static_assert(test<std::u8string_view>());
#endif

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// <string_view>

// template<class charT, class traits>
// constexpr bool operator!=(basic_string_view<charT, traits> lhs, basic_string_view<charT, traits> rhs);
// (plus "sufficient additional overloads" to make implicit conversions work as intended)

#include <string_view>
#include <cassert>
#include <string>

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

template<class T>
struct ConvertibleTo {
T t_;
TEST_CONSTEXPR explicit ConvertibleTo(T t) : t_(t) {}
TEST_CONSTEXPR operator T() const {
return t_;
}
};

template<class SV>
TEST_CONSTEXPR_CXX14 bool test()
{
typedef typename SV::value_type CharT;
typedef typename SV::traits_type Traits;

// Test the behavior of the operator, both with and without implicit conversions.
SV v[] = {
SV(MAKE_CSTRING(CharT, "")),
SV(MAKE_CSTRING(CharT, "abc")),
SV(MAKE_CSTRING(CharT, "abcdef")),
SV(MAKE_CSTRING(CharT, "acb")),
};
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
// See http://eel.is/c++draft/string.view#tab:string.view.comparison.overloads
bool expected = (i != j);
assert((v[i] != v[j]) == expected);
assert((v[i].data() != v[j]) == expected);
assert((v[i] != v[j].data()) == expected);
assert((ConvertibleTo<SV>(v[i]) != v[j]) == expected);
assert((v[i] != ConvertibleTo<SV>(v[j])) == expected);

if (!TEST_IS_CONSTANT_EVALUATED) {
// TODO FIXME: once P0980 "Making std::string constexpr" is implemented
assert((std::basic_string<CharT, Traits>(v[i]) != v[j]) == expected);
assert((v[i] != std::basic_string<CharT, Traits>(v[j])) == expected);
}
}
}

// Test its behavior with embedded null bytes.
SV abc = SV(MAKE_CSTRING(CharT, "abc"));
SV abc0def = SV(MAKE_CSTRING(CharT, "abc\0def"), 7);
SV abcdef = SV(MAKE_CSTRING(CharT, "abcdef"));
assert((abc != abc0def) == true);
assert((abc != abcdef) == true);
assert((abc0def != abc) == true);
assert((abc0def != abcdef) == true);
assert((abcdef != abc) == true);
assert((abcdef != abc0def) == true);

assert((abc.data() != abc0def) == true);
assert((abc0def != abc.data()) == true);

if (!TEST_IS_CONSTANT_EVALUATED) {
// TODO FIXME: once P0980 "Making std::string constexpr" is implemented
assert((std::basic_string<CharT, Traits>(abc) != abc0def) == true);
assert((abc0def != std::basic_string<CharT, Traits>(abc)) == true);
}

return true;
}

int main(int, char**)
{
test<std::string_view>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<std::wstring_view>();
#endif
#if TEST_STD_VER >= 11
test<std::u16string_view>();
test<std::u32string_view>();
#endif
#if TEST_STD_VER > 14
static_assert(test<std::string_view>(), "");
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
static_assert(test<std::wstring_view>(), "");
#endif
static_assert(test<std::u16string_view>(), "");
static_assert(test<std::u32string_view>(), "");
#endif

#if TEST_STD_VER > 11
test<std::basic_string_view<char, constexpr_char_traits<char>>>();
static_assert(test<std::basic_string_view<char, constexpr_char_traits<char>>>(), "");
#endif

#if TEST_STD_VER > 17
test<std::u8string_view>();
static_assert(test<std::u8string_view>());
#endif

return 0;
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

111 changes: 67 additions & 44 deletions libcxx/test/support/make_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,69 +11,92 @@

#include "test_macros.h"

#if TEST_STD_VER < 11
#error This header requires C++11 or greater
#endif

#include <string>
#include <string_view>

#ifndef TEST_HAS_NO_WIDE_CHARACTERS
# define MKSTR_WCHAR_ONLY(...) __VA_ARGS__
# define MKSTR_AS_WCHAR_LITERAL(x) TEST_CONCAT(L, x), sizeof(TEST_CONCAT(L, x)) / sizeof(wchar_t) - 1
#else
# define MKSTR_WCHAR_ONLY(...)
#endif

#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
#define CHAR8_ONLY(x) x,
#define MKSTR_CHAR8_ONLY(...) __VA_ARGS__
#define MKSTR_AS_U8_LITERAL(x) TEST_CONCAT(u8, x), sizeof(TEST_CONCAT(u8, x)) / sizeof(char8_t) - 1
#else
#define CHAR8_ONLY(x)
#define MKSTR_CHAR8_ONLY(...)
#endif

#ifndef TEST_HAS_NO_WIDE_CHARACTERS
# define IF_WIDE_CHARACTERS(...) __VA_ARGS__
#if TEST_STD_VER >= 11
#define MKSTR_CXX11_ONLY(...) __VA_ARGS__
#define MKSTR_AS_U16_LITERAL(x) TEST_CONCAT(u, x), sizeof(TEST_CONCAT(u, x)) / sizeof(char16_t) - 1
#define MKSTR_AS_U32_LITERAL(x) TEST_CONCAT(U, x), sizeof(TEST_CONCAT(U, x)) / sizeof(char32_t) - 1
#else
# define IF_WIDE_CHARACTERS(...) /* nothing */
#define MKSTR_CXX11_ONLY(...)
#endif

#define MKSTR(Str) \
{ \
Str, IF_WIDE_CHARACTERS(TEST_CONCAT(L, Str),) \
CHAR8_ONLY(TEST_CONCAT(u8, Str)) TEST_CONCAT(u, Str), \
TEST_CONCAT(U, Str) \
}
#define MKSTR(Str) MultiStringType( \
MKSTR_WCHAR_ONLY(MKSTR_AS_WCHAR_LITERAL(Str),) \
MKSTR_CHAR8_ONLY(MKSTR_AS_U8_LITERAL(Str),) \
MKSTR_CXX11_ONLY(MKSTR_AS_U16_LITERAL(Str), \
MKSTR_AS_U32_LITERAL(Str),) \
Str, sizeof(Str) - 1 \
)

#define MKSTR_LEN(CharT, Str) MKSTR(Str).length((const CharT*)0)

struct MultiStringType {
const char* s;
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
const wchar_t* w;
#endif
#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
const char8_t* u8;
#endif
const char16_t* u16;
const char32_t* u32;
MKSTR_WCHAR_ONLY(const wchar_t* w_; size_t wn_; )
MKSTR_CHAR8_ONLY(const char8_t* u8_; size_t u8n_; )
MKSTR_CXX11_ONLY(const char16_t* u16_; size_t u16n_; )
MKSTR_CXX11_ONLY(const char32_t* u32_; size_t u32n_; )
const char* s_; size_t sn_;

constexpr operator const char*() const { return s; }
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
constexpr operator const wchar_t*() const { return w; }
#endif
#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
constexpr operator const char8_t*() const { return u8; }
#endif
constexpr operator const char16_t*() const { return u16; }
constexpr operator const char32_t*() const { return u32; }
TEST_CONSTEXPR MultiStringType(
MKSTR_WCHAR_ONLY(const wchar_t *w, size_t wn,)
MKSTR_CHAR8_ONLY(const char8_t *u8, size_t u8n,)
MKSTR_CXX11_ONLY(const char16_t *u16, size_t u16n,)
MKSTR_CXX11_ONLY(const char32_t *u32, size_t u32n,)
const char *s, size_t sn)
: MKSTR_WCHAR_ONLY(w_(w), wn_(wn),)
MKSTR_CHAR8_ONLY(u8_(u8), u8n_(u8n),)
MKSTR_CXX11_ONLY(u16_(u16), u16n_(u16n),)
MKSTR_CXX11_ONLY(u32_(u32), u32n_(u32n),)
s_(s), sn_(sn) {}

TEST_CONSTEXPR const char *as_ptr(const char*) const { return s_; }
MKSTR_WCHAR_ONLY(TEST_CONSTEXPR const wchar_t *as_ptr(const wchar_t*) const { return w_; })
MKSTR_CHAR8_ONLY(constexpr const char8_t *as_ptr(const char8_t*) const { return u8_; })
MKSTR_CXX11_ONLY(constexpr const char16_t *as_ptr(const char16_t*) const { return u16_; })
MKSTR_CXX11_ONLY(constexpr const char32_t *as_ptr(const char32_t*) const { return u32_; })

TEST_CONSTEXPR size_t length(const char*) const { return sn_; }
MKSTR_WCHAR_ONLY(TEST_CONSTEXPR size_t length(const wchar_t*) const { return wn_; })
MKSTR_CHAR8_ONLY(constexpr size_t length(const char8_t*) const { return u8n_; })
MKSTR_CXX11_ONLY(constexpr size_t length(const char16_t*) const { return u16n_; })
MKSTR_CXX11_ONLY(constexpr size_t length(const char32_t*) const { return u32n_; })

// These implicit conversions are used by some tests. TODO: maybe eliminate them?
TEST_CONSTEXPR operator const char*() const { return s_; }
MKSTR_WCHAR_ONLY(TEST_CONSTEXPR operator const wchar_t*() const { return w_; })
MKSTR_CHAR8_ONLY(constexpr operator const char8_t*() const { return u8_; })
MKSTR_CXX11_ONLY(constexpr operator const char16_t*() const { return u16_; })
MKSTR_CXX11_ONLY(constexpr operator const char32_t*() const { return u32_; })
};

// Helper to convert a const char* string to a basic_string<CharT>.
// Helper to convert a const char* string to a const CharT*.
// This helper is used in unit tests to make them generic. The input should be
// valid ASCII which means the input is also valid UTF-8.
#define MAKE_CSTRING(CharT, Str) \
MKSTR(Str).as_ptr((const CharT*)0)

// Like MAKE_CSTRING but makes a basic_string<CharT>. Embedded nulls are OK.
#define MAKE_STRING(CharT, Str) \
std::basic_string<CharT> { \
static_cast<const CharT*>(MultiStringType MKSTR(Str)) \
}
std::basic_string<CharT>(MAKE_CSTRING(CharT, Str), MKSTR_LEN(CharT, Str))

// Like MAKE_CSTRING but makes a basic_string_view<CharT>. Embedded nulls are OK.
#define MAKE_STRING_VIEW(CharT, Str) \
std::basic_string_view<CharT> { \
static_cast<const CharT*>(MultiStringType MKSTR(Str)) \
}

// Like MAKE_STRING but converts to a const CharT*.
#define MAKE_CSTRING(CharT, Str) \
static_cast<const CharT*>(MultiStringType MKSTR(Str))
std::basic_string_view<CharT>(MAKE_CSTRING(CharT, Str), MKSTR_LEN(CharT, Str))

#endif
6 changes: 4 additions & 2 deletions libcxx/test/support/test_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,11 @@
#endif

#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
# define TEST_IS_CONSTANT_EVALUATED std::is_constant_evaluated()
# define TEST_IS_CONSTANT_EVALUATED std::is_constant_evaluated()
#elif __has_builtin(__builtin_is_constant_evaluated)
# define TEST_IS_CONSTANT_EVALUATED __builtin_is_constant_evaluated()
#else
# define TEST_IS_CONSTANT_EVALUATED false
# define TEST_IS_CONSTANT_EVALUATED false
#endif

#if TEST_STD_VER >= 14
Expand Down