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