brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.2 KiB · dc57c91 Raw
116 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++1710// TODO: Change to XFAIL once https://llvm.org/PR40995 is fixed11// UNSUPPORTED: availability-pmr-missing12 13// This test ensures that we properly propagate allocators from ostringstream's14// inner string object to the new string returned from .str().15// `str() const&` is specified to preserve the allocator (not copy the string).16// `str() &&` isn't specified, but should preserve the allocator (move the string).17 18#include <cassert>19#include <memory>20#include <memory_resource>21#include <sstream>22#include <string>23#include <type_traits>24 25#include "make_string.h"26#include "test_allocator.h"27#include "test_macros.h"28 29template <class CharT>30void test_soccc_behavior() {31  using Alloc = SocccAllocator<CharT>;32  using SS    = std::basic_ostringstream<CharT, std::char_traits<CharT>, Alloc>;33  using S     = std::basic_string<CharT, std::char_traits<CharT>, Alloc>;34  {35    SS ss = SS(std::ios_base::out, Alloc(10));36 37    // [stringbuf.members]/6 specifies that the allocator is copied,38    // not select_on_container_copy_construction'ed.39    //40    S copied = ss.str();41    assert(copied.get_allocator().count_ == 10);42    assert(ss.rdbuf()->get_allocator().count_ == 10);43    assert(copied.empty());44 45    // sanity-check that SOCCC does in fact work46    assert(S(copied).get_allocator().count_ == 11);47 48    // [stringbuf.members]/10 doesn't specify the allocator to use,49    // but copying the allocator as-if-by moving the string makes sense.50    //51    S moved = std::move(ss).str();52    assert(moved.get_allocator().count_ == 10);53    assert(ss.rdbuf()->get_allocator().count_ == 10);54    assert(moved.empty());55  }56}57 58template <class CharT>59void test_allocation_is_pilfered() {60  using SS = std::basic_ostringstream<CharT, std::char_traits<CharT>, std::pmr::polymorphic_allocator<CharT>>;61  using S  = std::pmr::basic_string<CharT>;62  alignas(void*) char buf[80 * sizeof(CharT)];63  const CharT* initial =64      MAKE_CSTRING(CharT, "a very long string that exceeds the small string optimization buffer length");65  {66    std::pmr::set_default_resource(std::pmr::null_memory_resource());67    auto mr1 = std::pmr::monotonic_buffer_resource(buf, sizeof(buf), std::pmr::null_memory_resource());68    SS ss    = SS(S(initial, &mr1));69    S s      = std::move(ss).str();70    assert(s == initial);71  }72}73 74template <class CharT>75void test_no_foreign_allocations() {76  using SS = std::basic_ostringstream<CharT, std::char_traits<CharT>, std::pmr::polymorphic_allocator<CharT>>;77  using S  = std::pmr::basic_string<CharT>;78  const CharT* initial =79      MAKE_CSTRING(CharT, "a very long string that exceeds the small string optimization buffer length");80  {81    std::pmr::set_default_resource(std::pmr::null_memory_resource());82    auto mr1 = std::pmr::monotonic_buffer_resource(std::pmr::new_delete_resource());83    auto ss  = SS(S(initial, &mr1));84    assert(ss.rdbuf()->get_allocator().resource() == &mr1);85 86    // [stringbuf.members]/6 specifies that the result of `str() const &`87    // does NOT use the default allocator; it uses the original allocator.88    //89    S copied = ss.str();90    assert(copied.get_allocator().resource() == &mr1);91    assert(ss.rdbuf()->get_allocator().resource() == &mr1);92    assert(copied == initial);93 94    // [stringbuf.members]/10 doesn't specify the allocator to use,95    // but copying the allocator as-if-by moving the string makes sense.96    //97    S moved = std::move(ss).str();98    assert(moved.get_allocator().resource() == &mr1);99    assert(ss.rdbuf()->get_allocator().resource() == &mr1);100    assert(moved == initial);101  }102}103 104int main(int, char**) {105  test_soccc_behavior<char>();106  test_allocation_is_pilfered<char>();107  test_no_foreign_allocations<char>();108#ifndef TEST_HAS_NO_WIDE_CHARACTERS109  test_soccc_behavior<wchar_t>();110  test_allocation_is_pilfered<wchar_t>();111  test_no_foreign_allocations<wchar_t>();112#endif113 114  return 0;115}116