1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 10 11 // <string> 12 13 // constexpr basic_string(basic_string&& str, size_type pos, const Allocator& a = Allocator()); 14 // constexpr basic_string(basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator()); 15 16 #include <cassert> 17 #include <string> 18 19 #include "constexpr_char_traits.h" 20 #include "count_new.h" 21 #include "make_string.h" 22 #include "min_allocator.h" 23 #include "test_allocator.h" 24 #include "test_macros.h" 25 26 #define STR(string) MAKE_CSTRING(typename S::value_type, string) 27 28 constexpr struct should_throw_exception_t { 29 } should_throw_exception; 30 31 template <class S> 32 constexpr void test_string_pos(S orig, typename S::size_type pos, S expected) { 33 #ifdef _LIBCPP_VERSION 34 ConstexprDisableAllocationGuard g; 35 #endif 36 S substr(std::move(orig), pos); 37 LIBCPP_ASSERT(orig.__invariants()); 38 LIBCPP_ASSERT(orig.empty()); 39 LIBCPP_ASSERT(substr.__invariants()); 40 assert(substr == expected); 41 } 42 43 template <class S> 44 constexpr void test_string_pos(S orig, typename S::size_type pos, should_throw_exception_t) { 45 #ifndef TEST_HAS_NO_EXCEPTIONS 46 if (!std::is_constant_evaluated()) { 47 try { 48 [[maybe_unused]] S substr = S(std::move(orig), pos); 49 assert(false); 50 } catch (const std::out_of_range&) { 51 } 52 } 53 #else 54 (void)orig; 55 (void)pos; 56 #endif 57 } 58 59 template <class S> 60 constexpr void 61 test_string_pos_alloc(S orig, typename S::size_type pos, const typename S::allocator_type& alloc, S expected) { 62 S substr(std::move(orig), pos, alloc); 63 LIBCPP_ASSERT(orig.__invariants()); 64 LIBCPP_ASSERT(substr.__invariants()); 65 assert(substr == expected); 66 assert(substr.get_allocator() == alloc); 67 } 68 69 template <class S> 70 constexpr void test_string_pos_alloc( 71 S orig, typename S::size_type pos, const typename S::allocator_type& alloc, should_throw_exception_t) { 72 #ifndef TEST_HAS_NO_EXCEPTIONS 73 if (!std::is_constant_evaluated()) { 74 try { 75 [[maybe_unused]] S substr = S(std::move(orig), pos, alloc); 76 assert(false); 77 } catch (const std::out_of_range&) { 78 } 79 } 80 #else 81 (void)orig; 82 (void)pos; 83 (void)alloc; 84 #endif 85 } 86 87 template <class S> 88 constexpr void test_string_pos_n(S orig, typename S::size_type pos, typename S::size_type n, S expected) { 89 #ifdef _LIBCPP_VERSION 90 ConstexprDisableAllocationGuard g; 91 #endif 92 S substr(std::move(orig), pos, n); 93 LIBCPP_ASSERT(orig.__invariants()); 94 LIBCPP_ASSERT(orig.empty()); 95 LIBCPP_ASSERT(substr.__invariants()); 96 assert(substr == expected); 97 } 98 99 template <class S> 100 constexpr void test_string_pos_n(S orig, typename S::size_type pos, typename S::size_type n, should_throw_exception_t) { 101 #ifndef TEST_HAS_NO_EXCEPTIONS 102 if (!std::is_constant_evaluated()) { 103 try { 104 [[maybe_unused]] S substr = S(std::move(orig), pos, n); 105 assert(false); 106 } catch (const std::out_of_range&) { 107 } 108 } 109 #else 110 (void)orig; 111 (void)pos; 112 (void)n; 113 #endif 114 } 115 116 template <class S> 117 constexpr void test_string_pos_n_alloc( 118 S orig, typename S::size_type pos, typename S::size_type n, const typename S::allocator_type& alloc, S expected) { 119 S substr(std::move(orig), pos, n, alloc); 120 LIBCPP_ASSERT(orig.__invariants()); 121 LIBCPP_ASSERT(substr.__invariants()); 122 assert(substr == expected); 123 assert(substr.get_allocator() == alloc); 124 } 125 126 template <class S> 127 constexpr void test_string_pos_n_alloc( 128 S orig, 129 typename S::size_type pos, 130 typename S::size_type n, 131 const typename S::allocator_type& alloc, 132 should_throw_exception_t) { 133 #ifndef TEST_HAS_NO_EXCEPTIONS 134 if (!std::is_constant_evaluated()) { 135 try { 136 [[maybe_unused]] S substr = S(std::move(orig), pos, n, alloc); 137 assert(false); 138 } catch (const std::out_of_range&) { 139 } 140 } 141 #else 142 (void)orig; 143 (void)pos; 144 (void)n; 145 (void)alloc; 146 #endif 147 } 148 149 template <class S> 150 constexpr void test_string(const typename S::allocator_type& alloc) { 151 test_string_pos<S>(STR(""), 0, STR("")); 152 test_string_pos<S>(STR(""), 1, should_throw_exception); 153 test_string_pos<S>(STR("Banane"), 1, STR("anane")); 154 test_string_pos<S>(STR("Banane"), 6, STR("")); 155 test_string_pos<S>(STR("Banane"), 7, should_throw_exception); 156 test_string_pos<S>(STR("long long string so no SSO"), 0, STR("long long string so no SSO")); 157 test_string_pos<S>(STR("long long string so no SSO"), 10, STR("string so no SSO")); 158 test_string_pos<S>(STR("long long string so no SSO"), 26, STR("")); 159 test_string_pos<S>(STR("long long string so no SSO"), 27, should_throw_exception); 160 161 test_string_pos_alloc<S>(STR(""), 0, alloc, STR("")); 162 test_string_pos_alloc<S>(STR(""), 1, alloc, should_throw_exception); 163 test_string_pos_alloc<S>(STR("Banane"), 1, alloc, STR("anane")); 164 test_string_pos_alloc<S>(STR("Banane"), 6, alloc, STR("")); 165 test_string_pos_alloc<S>(STR("Banane"), 7, alloc, should_throw_exception); 166 test_string_pos_alloc<S>(STR("long long string so no SSO"), 0, alloc, STR("long long string so no SSO")); 167 test_string_pos_alloc<S>(STR("long long string so no SSO"), 10, alloc, STR("string so no SSO")); 168 test_string_pos_alloc<S>(STR("long long string so no SSO"), 26, alloc, STR("")); 169 test_string_pos_alloc<S>(STR("long long string so no SSO"), 27, alloc, should_throw_exception); 170 171 test_string_pos_n<S>(STR(""), 0, 0, STR("")); 172 test_string_pos_n<S>(STR(""), 0, 1, STR("")); 173 test_string_pos_n<S>(STR(""), 1, 0, should_throw_exception); 174 test_string_pos_n<S>(STR(""), 1, 1, should_throw_exception); 175 test_string_pos_n<S>(STR("Banane"), 1, 10, STR("anane")); 176 test_string_pos_n<S>(STR("Banane"), 6, 0, STR("")); 177 test_string_pos_n<S>(STR("Banane"), 6, 5, STR("")); 178 test_string_pos_n<S>(STR("Banane"), 7, 10, should_throw_exception); 179 test_string_pos_n<S>(STR("long long string so no SSO"), 0, 10, STR("long long ")); 180 test_string_pos_n<S>(STR("long long string so no SSO"), 10, 8, STR("string s")); 181 test_string_pos_n<S>(STR("long long string so no SSO"), 20, 10, STR("no SSO")); 182 test_string_pos_n<S>(STR("long long string so no SSO"), 26, 10, STR("")); 183 test_string_pos_n<S>(STR("long long string so no SSO"), 27, 10, should_throw_exception); 184 185 test_string_pos_n_alloc<S>(STR(""), 0, 0, alloc, STR("")); 186 test_string_pos_n_alloc<S>(STR(""), 0, 1, alloc, STR("")); 187 test_string_pos_n_alloc<S>(STR(""), 1, 0, alloc, should_throw_exception); 188 test_string_pos_n_alloc<S>(STR(""), 1, 1, alloc, should_throw_exception); 189 test_string_pos_n_alloc<S>(STR("Banane"), 1, 10, alloc, STR("anane")); 190 test_string_pos_n_alloc<S>(STR("Banane"), 6, 0, alloc, STR("")); 191 test_string_pos_n_alloc<S>(STR("Banane"), 6, 5, alloc, STR("")); 192 test_string_pos_n_alloc<S>(STR("Banane"), 7, 10, alloc, should_throw_exception); 193 test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 0, 10, alloc, STR("long long ")); 194 test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 10, 8, alloc, STR("string s")); 195 test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 20, 10, alloc, STR("no SSO")); 196 test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 26, 10, alloc, STR("")); 197 test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 27, 10, alloc, should_throw_exception); 198 } 199 200 template <class CharT, class CharTraits> 201 constexpr void test_allocators() { 202 test_string<std::basic_string<CharT, CharTraits, std::allocator<CharT>>>(std::allocator<CharT>{}); 203 test_string<std::basic_string<CharT, CharTraits, min_allocator<CharT>>>(min_allocator<CharT>{}); 204 test_string<std::basic_string<CharT, CharTraits, test_allocator<CharT>>>(test_allocator<CharT>{42}); 205 } 206 207 template <class CharT> 208 constexpr bool test_char_traits() { 209 test_allocators<CharT, std::char_traits<CharT>>(); 210 test_allocators<CharT, constexpr_char_traits<CharT>>(); 211 212 return true; 213 } 214 215 int main(int, char**) { 216 // TODO: put these into a single function when we increase the constexpr step limit 217 test_char_traits<char>(); 218 static_assert(test_char_traits<char>()); 219 test_char_traits<char16_t>(); 220 static_assert(test_char_traits<char16_t>()); 221 test_char_traits<char32_t>(); 222 static_assert(test_char_traits<char32_t>()); 223 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 224 test_char_traits<wchar_t>(); 225 static_assert(test_char_traits<wchar_t>()); 226 #endif 227 #ifndef TEST_HAS_NO_CHAR8_T 228 test_char_traits<char8_t>(); 229 static_assert(test_char_traits<char8_t>()); 230 #endif 231 232 return 0; 233 } 234