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