137 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// <string>10 11// basic_string(const basic_string& str, const Allocator& alloc); // constexpr since C++2012 13#include <string>14#include <cassert>15 16#include "test_macros.h"17#include "test_allocator.h"18#include "min_allocator.h"19#include "asan_testing.h"20 21#ifndef TEST_HAS_NO_EXCEPTIONS22struct alloc_imp {23 bool active;24 25 TEST_CONSTEXPR alloc_imp() : active(true) {}26 27 template <class T>28 T* allocate(std::size_t n) {29 if (active)30 return static_cast<T*>(std::malloc(n * sizeof(T)));31 else32 throw std::bad_alloc();33 }34 35 template <class T>36 void deallocate(T* p, std::size_t) {37 std::free(p);38 }39 void activate() { active = true; }40 void deactivate() { active = false; }41};42 43template <class T>44struct poca_alloc {45 typedef T value_type;46 typedef std::true_type propagate_on_container_copy_assignment;47 48 alloc_imp* imp;49 50 TEST_CONSTEXPR poca_alloc(alloc_imp* imp_) : imp(imp_) {}51 52 template <class U>53 TEST_CONSTEXPR poca_alloc(const poca_alloc<U>& other) : imp(other.imp) {}54 55 T* allocate(std::size_t n) { return imp->allocate<T>(n); }56 void deallocate(T* p, std::size_t n) { imp->deallocate(p, n); }57};58 59template <typename T, typename U>60bool operator==(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs) {61 return lhs.imp == rhs.imp;62}63 64template <typename T, typename U>65bool operator!=(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs) {66 return lhs.imp != rhs.imp;67}68#endif69 70template <class S>71TEST_CONSTEXPR_CXX20 void test(S s1, const typename S::allocator_type& a) {72 S s2(s1, a);73 LIBCPP_ASSERT(s2.__invariants());74 assert(s2 == s1);75 assert(s2.capacity() >= s2.size());76 assert(s2.get_allocator() == a);77 LIBCPP_ASSERT(is_string_asan_correct(s1));78 LIBCPP_ASSERT(is_string_asan_correct(s2));79}80 81template <class Alloc>82TEST_CONSTEXPR_CXX20 void test_string(const Alloc& a) {83 typedef std::basic_string<char, std::char_traits<char>, Alloc> S;84 test(S(), Alloc(a));85 test(S("1"), Alloc(a));86 test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), Alloc(a));87}88 89TEST_CONSTEXPR_CXX20 bool test() {90 test_string(std::allocator<char>());91 test_string(test_allocator<char>());92 test_string(test_allocator<char>(3));93#if TEST_STD_VER >= 1194 test_string(min_allocator<char>());95 test_string(safe_allocator<char>());96#endif97 98#if TEST_STD_VER >= 1199# ifndef TEST_HAS_NO_EXCEPTIONS100 if (!TEST_IS_CONSTANT_EVALUATED) {101 typedef poca_alloc<char> A;102 typedef std::basic_string<char, std::char_traits<char>, A> S;103 const char* p1 = "This is my first string";104 const char* p2 = "This is my second string";105 106 alloc_imp imp1;107 alloc_imp imp2;108 S s1(p1, A(&imp1));109 S s2(p2, A(&imp2));110 111 assert(s1 == p1);112 assert(s2 == p2);113 114 imp2.deactivate();115 try {116 s1 = s2;117 assert(false);118 } catch (std::bad_alloc&) {119 }120 assert(s1 == p1);121 assert(s2 == p2);122 }123# endif124#endif125 126 return true;127}128 129int main(int, char**) {130 test();131#if TEST_STD_VER > 17132 static_assert(test());133#endif134 135 return 0;136}137