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