From: Jonathan Wakely Date: Tue, 24 Jul 2018 21:09:55 +0000 (+0100) Subject: Add initial version of C++17 header X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dfaa3c47cc0a5e858ff45e0f2ab4d686048f718e;p=gcc.git Add initial version of C++17 header This is missing the synchronized_pool_resource and unsynchronized_pool_resource classes but is otherwise complete. This is a new implementation, not based on the existing code in , but memory_resource and polymorphic_allocator ended up looking almost the same anyway. The constant_init kluge in src/c++17/memory_resource.cc is apparently due to Richard Smith and ensures that the objects are constructed during constant initialiation phase and not destroyed (because the constant_init destructor doesn't destroy the union member and the storage is not reused). * config/abi/pre/gnu.ver: Export new symbols. * configure: Regenerate. * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/precompiled/stdc++.h: Include for C++17. * include/std/memory_resource: New header. (memory_resource, polymorphic_allocator, new_delete_resource) (null_memory_resource, set_default_resource, get_default_resource) (pool_options, monotonic_buffer_resource): Define. * src/Makefile.am: Add c++17 directory. * src/Makefile.in: Regenerate. * src/c++11/Makefile.am: Fix comment. * src/c++17/Makefile.am: Add makefile for new sub-directory. * src/c++17/Makefile.in: Generate. * src/c++17/memory_resource.cc: New. (newdel_res_t, null_res_t, constant_init, newdel_res, null_res) (default_res, new_delete_resource, null_memory_resource) (set_default_resource, get_default_resource): Define. * testsuite/20_util/memory_resource/1.cc: New test. * testsuite/20_util/memory_resource/2.cc: New test. * testsuite/20_util/monotonic_buffer_resource/1.cc: New test. * testsuite/20_util/monotonic_buffer_resource/allocate.cc: New test. * testsuite/20_util/monotonic_buffer_resource/deallocate.cc: New test. * testsuite/20_util/monotonic_buffer_resource/release.cc: New test. * testsuite/20_util/monotonic_buffer_resource/upstream_resource.cc: New test. * testsuite/20_util/polymorphic_allocator/1.cc: New test. * testsuite/20_util/polymorphic_allocator/resource.cc: New test. * testsuite/20_util/polymorphic_allocator/select.cc: New test. * testsuite/util/testsuite_allocator.h (__gnu_test::memory_resource): Define concrete memory resource for testing. (__gnu_test::default_resource_mgr): Define RAII helper for changing default resource. From-SVN: r262953 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 91c0f4c0afe..bef5a97cd6e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,39 @@ 2018-07-24 Jonathan Wakely + * config/abi/pre/gnu.ver: Export new symbols. + * configure: Regenerate. + * include/Makefile.am: Add new header. + * include/Makefile.in: Regenerate. + * include/precompiled/stdc++.h: Include for C++17. + * include/std/memory_resource: New header. + (memory_resource, polymorphic_allocator, new_delete_resource) + (null_memory_resource, set_default_resource, get_default_resource) + (pool_options, monotonic_buffer_resource): Define. + * src/Makefile.am: Add c++17 directory. + * src/Makefile.in: Regenerate. + * src/c++11/Makefile.am: Fix comment. + * src/c++17/Makefile.am: Add makefile for new sub-directory. + * src/c++17/Makefile.in: Generate. + * src/c++17/memory_resource.cc: New. + (newdel_res_t, null_res_t, constant_init, newdel_res, null_res) + (default_res, new_delete_resource, null_memory_resource) + (set_default_resource, get_default_resource): Define. + * testsuite/20_util/memory_resource/1.cc: New test. + * testsuite/20_util/memory_resource/2.cc: New test. + * testsuite/20_util/monotonic_buffer_resource/1.cc: New test. + * testsuite/20_util/monotonic_buffer_resource/allocate.cc: New test. + * testsuite/20_util/monotonic_buffer_resource/deallocate.cc: New test. + * testsuite/20_util/monotonic_buffer_resource/release.cc: New test. + * testsuite/20_util/monotonic_buffer_resource/upstream_resource.cc: + New test. + * testsuite/20_util/polymorphic_allocator/1.cc: New test. + * testsuite/20_util/polymorphic_allocator/resource.cc: New test. + * testsuite/20_util/polymorphic_allocator/select.cc: New test. + * testsuite/util/testsuite_allocator.h (__gnu_test::memory_resource): + Define concrete memory resource for testing. + (__gnu_test::default_resource_mgr): Define RAII helper for changing + default resource. + PR libstdc++/86658 * include/bits/stl_algobase.h (__niter_wrap<_Iterator>): Pass unused parameter by reference, to avoid copying invalid iterators. diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index b09bdef6d09..36459e88b6a 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2039,6 +2039,11 @@ GLIBCXX_3.4.26 { _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]Ev; _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]Ev; + _ZNSt3pmr19new_delete_resourceEv; + _ZNSt3pmr20null_memory_resourceEv; + _ZNSt3pmr20get_default_resourceEv; + _ZNSt3pmr20set_default_resourceEPNS_15memory_resourceE; + } GLIBCXX_3.4.25; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 101dcd9cb7c..54a2e8a380e 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -4965,7 +4965,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; } # expandable list at autoconf time; the second provides an expandable list # (i.e., shell variable) at configure time. - SUBDIRS='include libsupc++ src src/c++98 src/c++11 src/filesystem doc po testsuite python' + SUBDIRS='include libsupc++ src src/c++98 src/c++11 src/c++17 src/filesystem doc po testsuite python' # These need to be absolute paths, yet at the same time need to # canonicalize only relative paths, because then amd will not unmount @@ -81841,7 +81841,7 @@ ac_config_files="$ac_config_files doc/xsl/customization.xsl" # append it here. Only modify Makefiles that have just been created. # # Also, get rid of this simulated-VPATH thing that automake does. -ac_config_files="$ac_config_files include/Makefile libsupc++/Makefile src/Makefile src/c++98/Makefile src/c++11/Makefile src/filesystem/Makefile doc/Makefile po/Makefile testsuite/Makefile python/Makefile" +ac_config_files="$ac_config_files include/Makefile libsupc++/Makefile src/Makefile src/c++98/Makefile src/c++11/Makefile src/c++17/Makefile src/filesystem/Makefile doc/Makefile po/Makefile testsuite/Makefile python/Makefile" ac_config_commands="$ac_config_commands generate-headers" @@ -83076,6 +83076,7 @@ do "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/c++98/Makefile") CONFIG_FILES="$CONFIG_FILES src/c++98/Makefile" ;; "src/c++11/Makefile") CONFIG_FILES="$CONFIG_FILES src/c++11/Makefile" ;; + "src/c++17/Makefile") CONFIG_FILES="$CONFIG_FILES src/c++17/Makefile" ;; "src/filesystem/Makefile") CONFIG_FILES="$CONFIG_FILES src/filesystem/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; @@ -84904,6 +84905,17 @@ _EOF ;; "src/c++11/Makefile":F) cat > vpsed$$ << \_EOF s!`test -f '$<' || echo '$(srcdir)/'`!! +_EOF + sed -f vpsed$$ $ac_file > tmp$$ + mv tmp$$ $ac_file + rm vpsed$$ + echo 'MULTISUBDIR =' >> $ac_file + ml_norecursion=yes + . ${multi_basedir}/config-ml.in + { ml_norecursion=; unset ml_norecursion;} + ;; + "src/c++17/Makefile":F) cat > vpsed$$ << \_EOF +s!`test -f '$<' || echo '$(srcdir)/'`!! _EOF sed -f vpsed$$ $ac_file > tmp$$ mv tmp$$ $ac_file diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index d1453a5abce..9daa8856e70 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -54,6 +54,7 @@ std_headers = \ ${std_srcdir}/locale \ ${std_srcdir}/map \ ${std_srcdir}/memory \ + ${std_srcdir}/memory_resource \ ${std_srcdir}/mutex \ ${std_srcdir}/numeric \ ${std_srcdir}/optional \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index ff3249e346e..a122c9cfe2c 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -347,6 +347,7 @@ std_headers = \ ${std_srcdir}/locale \ ${std_srcdir}/map \ ${std_srcdir}/memory \ + ${std_srcdir}/memory_resource \ ${std_srcdir}/mutex \ ${std_srcdir}/numeric \ ${std_srcdir}/optional \ diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h index 80769233eb3..1f537354052 100644 --- a/libstdc++-v3/include/precompiled/stdc++.h +++ b/libstdc++-v3/include/precompiled/stdc++.h @@ -128,7 +128,7 @@ // #include #include #include -// #include +#include #include #include #endif diff --git a/libstdc++-v3/include/std/memory_resource b/libstdc++-v3/include/std/memory_resource new file mode 100644 index 00000000000..b3f8f7d9477 --- /dev/null +++ b/libstdc++-v3/include/std/memory_resource @@ -0,0 +1,510 @@ +// -*- C++ -*- + +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/memory_resource + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_MEMORY_RESOURCE +#define _GLIBCXX_MEMORY_RESOURCE 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include // __ceil2, __log2p1 +#include // align, allocator_arg_t, __uses_alloc +#include // pair, index_sequence +#include // size_t, max_align_t +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace pmr +{ +// #define __cpp_lib_memory_resource 201603 + + class memory_resource; + + template + class polymorphic_allocator; + + // Global memory resources + memory_resource* new_delete_resource() noexcept; + memory_resource* null_memory_resource() noexcept; + memory_resource* set_default_resource(memory_resource* __r) noexcept; + memory_resource* get_default_resource() noexcept + __attribute__((__returns_nonnull__)); + + // Pool resource classes + struct pool_options; + class synchronized_pool_resource; + class unsynchronized_pool_resource; + class monotonic_buffer_resource; + + /// Class memory_resource + class memory_resource + { + static constexpr size_t _S_max_align = alignof(max_align_t); + + public: + memory_resource() = default; + memory_resource(const memory_resource&) = default; + virtual ~memory_resource() = default; + + memory_resource& operator=(const memory_resource&) = default; + + [[nodiscard]] + void* + allocate(size_t __bytes, size_t __alignment = _S_max_align) + __attribute__((__returns_nonnull__,__alloc_size__(2),__alloc_align__(3))) + { return do_allocate(__bytes, __alignment); } + + void + deallocate(void* __p, size_t __bytes, size_t __alignment = _S_max_align) + __attribute__((__nonnull__)) + { return do_deallocate(__p, __bytes, __alignment); } + + bool + is_equal(const memory_resource& __other) const noexcept + { return do_is_equal(__other); } + + private: + virtual void* + do_allocate(size_t __bytes, size_t __alignment) = 0; + + virtual void + do_deallocate(void* __p, size_t __bytes, size_t __alignment) = 0; + + virtual bool + do_is_equal(const memory_resource& __other) const noexcept = 0; + }; + + inline bool + operator==(const memory_resource& __a, const memory_resource& __b) noexcept + { return &__a == &__b || __a.is_equal(__b); } + + inline bool + operator!=(const memory_resource& __a, const memory_resource& __b) noexcept + { return !(__a == __b); } + + + // C++17 23.12.3 Class template polymorphic_allocator + template + class polymorphic_allocator + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2975. Missing case for pair construction in polymorphic allocators + template + struct __not_pair { using type = void; }; + + template + struct __not_pair> { }; + + public: + using value_type = _Tp; + + polymorphic_allocator() noexcept + : _M_resource(get_default_resource()) + { } + + polymorphic_allocator(memory_resource* __r) noexcept + __attribute__((__nonnull__)) + : _M_resource(__r) + { _GLIBCXX_DEBUG_ASSERT(__r); } + + polymorphic_allocator(const polymorphic_allocator& __other) = default; + + template + polymorphic_allocator(const polymorphic_allocator<_Up>& __x) noexcept + : _M_resource(__x.resource()) + { } + + polymorphic_allocator& + operator=(const polymorphic_allocator&) = delete; + + [[nodiscard]] + _Tp* + allocate(size_t __n) + __attribute__((__returns_nonnull__)) + { + if (__n > (numeric_limits::max() / sizeof(_Tp))) + std::__throw_bad_alloc(); + return static_cast<_Tp*>(_M_resource->allocate(__n * sizeof(_Tp), + alignof(_Tp))); + } + + void + deallocate(_Tp* __p, size_t __n) noexcept + __attribute__((__nonnull__)) + { _M_resource->deallocate(__p, __n * sizeof(_Tp), alignof(_Tp)); } + + template + __attribute__((__nonnull__)) + typename __not_pair<_Tp>::type + construct(_Tp1* __p, _Args&&... __args) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2969. polymorphic_allocator::construct() shouldn't pass resource() + auto __use_tag + = __use_alloc<_Tp1, polymorphic_allocator, _Args...>(*this); + _S_construct(__use_tag, __p, std::forward<_Args>(__args)...); + } + + template + __attribute__((__nonnull__)) + void + construct(pair<_Tp1, _Tp2>* __p, piecewise_construct_t, + tuple<_Args1...> __x, tuple<_Args2...> __y) + { + auto __x_tag = + __use_alloc<_Tp1, polymorphic_allocator, _Args1...>(*this); + auto __y_tag = + __use_alloc<_Tp2, polymorphic_allocator, _Args2...>(*this); + index_sequence_for<_Args1...> __x_i; + index_sequence_for<_Args2...> __y_i; + + ::new(__p) pair<_Tp1, _Tp2>(piecewise_construct, + _S_construct_p(__x_tag, __x, __x_i), + _S_construct_p(__y_tag, __y, __y_i)); + } + + template + __attribute__((__nonnull__)) + void + construct(pair<_Tp1, _Tp2>* __p) + { this->construct(__p, piecewise_construct, tuple<>(), tuple<>()); } + + template + __attribute__((__nonnull__)) + void + construct(pair<_Tp1, _Tp2>* __p, _Up&& __x, _Vp&& __y) + { + this->construct(__p, piecewise_construct, + forward_as_tuple(std::forward<_Up>(__x)), + forward_as_tuple(std::forward<_Vp>(__y))); + } + + template + __attribute__((__nonnull__)) + void + construct(pair<_Tp1, _Tp2>* __p, const std::pair<_Up, _Vp>& __pr) + { + this->construct(__p, piecewise_construct, + forward_as_tuple(__pr.first), + forward_as_tuple(__pr.second)); + } + + template + __attribute__((__nonnull__)) + void + construct(pair<_Tp1, _Tp2>* __p, pair<_Up, _Vp>&& __pr) + { + this->construct(__p, piecewise_construct, + forward_as_tuple(std::forward<_Up>(__pr.first)), + forward_as_tuple(std::forward<_Vp>(__pr.second))); + } + + template + __attribute__((__nonnull__)) + void + destroy(_Up* __p) + { __p->~_Up(); } + + polymorphic_allocator + select_on_container_copy_construction() const noexcept + { return polymorphic_allocator(); } + + memory_resource* + resource() const noexcept + __attribute__((__returns_nonnull__)) + { return _M_resource; } + + private: + using __uses_alloc1_ = __uses_alloc1; + using __uses_alloc2_ = __uses_alloc2; + + template + static void + _S_construct(__uses_alloc0, _Tp1* __p, _Args&&... __args) + { ::new(__p) _Tp1(std::forward<_Args>(__args)...); } + + template + static void + _S_construct(__uses_alloc1_ __ua, _Tp1* __p, _Args&&... __args) + { + ::new(__p) _Tp1(allocator_arg, *__ua._M_a, + std::forward<_Args>(__args)...); + } + + template + static void + _S_construct(__uses_alloc2_ __ua, _Tp1* __p, _Args&&... __args) + { ::new(__p) _Tp1(std::forward<_Args>(__args)..., *__ua._M_a); } + + template + static tuple<_Args&&...> + _S_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) + { return std::move(__t); } + + template + static tuple + _S_construct_p(__uses_alloc1_ __ua, index_sequence<_Ind...>, + tuple<_Args...>& __t) + { + return { + allocator_arg, *__ua._M_a, std::get<_Ind>(std::move(__t))... + }; + } + + template + static tuple<_Args&&..., polymorphic_allocator&> + _S_construct_p(__uses_alloc2_ __ua, index_sequence<_Ind...>, + tuple<_Args...>& __t) + { return { std::get<_Ind>(std::move(__t))..., *__ua._M_a }; } + + memory_resource* _M_resource; + }; + + template + inline bool + operator==(const polymorphic_allocator<_Tp1>& __a, + const polymorphic_allocator<_Tp2>& __b) noexcept + { return *__a.resource() == *__b.resource(); } + + template + inline bool + operator!=(const polymorphic_allocator<_Tp1>& __a, + const polymorphic_allocator<_Tp2>& __b) noexcept + { return !(__a == __b); } + + + struct pool_options + { + size_t max_blocks_per_chunk = 0; + size_t largest_required_pool_block = 0; + }; + + // TODO class synchronized_pool_resource; + // TODO class unsynchronized_pool_resource; + + class monotonic_buffer_resource : public memory_resource + { + public: + explicit + monotonic_buffer_resource(memory_resource* __upstream) noexcept + __attribute__((__nonnull__)) + : _M_upstream(__upstream) + { _GLIBCXX_DEBUG_ASSERT(__upstream != nullptr); } + + monotonic_buffer_resource(size_t __initial_size, + memory_resource* __upstream) noexcept + __attribute__((__nonnull__)) + : _M_next_bufsiz(__initial_size), + _M_upstream(__upstream) + { + _GLIBCXX_DEBUG_ASSERT(__upstream != nullptr); + _GLIBCXX_DEBUG_ASSERT(__initial_size > 0); + } + + monotonic_buffer_resource(void* __buffer, size_t __buffer_size, + memory_resource* __upstream) noexcept + __attribute__((__nonnull__(4))) + : _M_current_buf(__buffer), _M_avail(__buffer_size), + _M_next_bufsiz(_S_next_bufsize(__buffer_size)), + _M_upstream(__upstream), + _M_orig_buf(__buffer), _M_orig_size(__buffer_size) + { + _GLIBCXX_DEBUG_ASSERT(__upstream != nullptr); + _GLIBCXX_DEBUG_ASSERT(__buffer != nullptr || __buffer_size == 0); + } + + monotonic_buffer_resource() noexcept + : monotonic_buffer_resource(get_default_resource()) + { } + + explicit + monotonic_buffer_resource(size_t __initial_size) noexcept + : monotonic_buffer_resource(__initial_size, get_default_resource()) + { } + + monotonic_buffer_resource(void* __buffer, size_t __buffer_size) noexcept + : monotonic_buffer_resource(__buffer, __buffer_size, get_default_resource()) + { } + + monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; + + virtual ~monotonic_buffer_resource() { release(); } + + monotonic_buffer_resource& + operator=(const monotonic_buffer_resource&) = delete; + + void + release() noexcept + { + _Chunk::release(_M_head, _M_upstream); + + // reset to initial state at contruction: + if ((_M_current_buf = _M_orig_buf)) + { + _M_avail = _M_orig_size; + _M_next_bufsiz = _S_next_bufsize(_M_orig_size); + } + else + { + _M_avail = 0; + _M_next_bufsiz = _M_orig_size; + } + } + + memory_resource* + upstream_resource() const noexcept + __attribute__((__returns_nonnull__)) + { return _M_upstream; } + + protected: + void* + do_allocate(size_t __bytes, size_t __alignment) override + { + if (__bytes == 0) + __bytes = 1; // Ensures we don't return the same pointer twice. + + if (auto __p = std::align(__alignment, __bytes, _M_current_buf, _M_avail)) + { + _M_current_buf = (char*)_M_current_buf + __bytes; + _M_avail -= __bytes; + return __p; + } + + const size_t __n = std::max(__bytes, _M_next_bufsiz); + const size_t __m = std::max(__alignment, alignof(std::max_align_t)); + auto [__p, __size] = _Chunk::allocate(_M_upstream, __n, __m, _M_head); + _M_current_buf = (char*)__p + __bytes; + _M_avail = __size - __bytes; + _M_next_bufsiz *= _S_growth_factor; + return __p; + } + + void + do_deallocate(void*, size_t, size_t) override + { } + + bool + do_is_equal(const memory_resource& __other) const noexcept override + { return this == &__other; } + + private: + static size_t + _S_next_bufsize(size_t __buffer_size) noexcept + { + if (__buffer_size == 0) + __buffer_size = 1; + return __buffer_size * _S_growth_factor; + } + + static constexpr size_t _S_init_bufsize = 128 * sizeof(void*); + static constexpr float _S_growth_factor = 1.5; + + void* _M_current_buf = nullptr; + size_t _M_avail = 0; + size_t _M_next_bufsiz = _S_init_bufsize; + + // Initial values set at construction and reused by release(): + memory_resource* const _M_upstream; + void* const _M_orig_buf = nullptr; + size_t const _M_orig_size = _M_next_bufsiz; + + // Memory allocated by the upstream resource is managed in a linked list + // of _Chunk objects. A _Chunk object recording the size and alignment of + // the allocated block and a pointer to the previous chunk is placed + // at end of the block. + class _Chunk + { + public: + // Return the address and size of a block of memory allocated from __r, + // of at least __size bytes and aligned to __align. + // Add a new _Chunk to the front of the linked list at __head. + static pair + allocate(memory_resource* __r, size_t __size, size_t __align, + _Chunk*& __head) + { + __size = std::__ceil2(__size + sizeof(_Chunk)); + void* __p = __r->allocate(__size, __align); + // Add a chunk defined by (__p, __size, __align) to linked list __head. + void* const __back = (char*)__p + __size - sizeof(_Chunk); + __head = ::new(__back) _Chunk(__size, __align, __head); + return { __p, __size - sizeof(_Chunk) }; + } + + // Return every chunk in linked list __head to resource __r. + static void + release(_Chunk*& __head, memory_resource* __r) noexcept + { + _Chunk* __next = __head; + __head = nullptr; + while (__next) + { + _Chunk* __ch = __next; + __builtin_memcpy(&__next, __ch->_M_next, sizeof(_Chunk*)); + + __glibcxx_assert(__ch->_M_canary != 0); + __glibcxx_assert(__ch->_M_canary == (__ch->_M_size|__ch->_M_align)); + + if (__ch->_M_canary != (__ch->_M_size | __ch->_M_align)) + return; // buffer overflow detected! + + size_t __size = (1u << __ch->_M_size); + size_t __align = (1u << __ch->_M_align); + void* __start = (char*)(__ch + 1) - __size; + __r->deallocate(__start, __size, __align); + } + } + + private: + _Chunk(size_t __size, size_t __align, _Chunk* __next) noexcept + : _M_size(std::__log2p1(__size) - 1), + _M_align(std::__log2p1(__align) - 1) + { + __builtin_memcpy(_M_next, &__next, sizeof(__next)); + _M_canary = _M_size | _M_align; + } + + unsigned char _M_canary; + unsigned char _M_size; + unsigned char _M_align; + unsigned char _M_next[sizeof(_Chunk*)]; + }; + static_assert(alignof(_Chunk) == 1); + + _Chunk* _M_head = nullptr; + }; + +} // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 +#endif // _GLIBCXX_MEMORY_RESOURCE diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am index ba30dde8fec..09edcdbc471 100644 --- a/libstdc++-v3/src/Makefile.am +++ b/libstdc++-v3/src/Makefile.am @@ -28,7 +28,7 @@ else filesystem_dir = endif -SUBDIRS = c++98 c++11 $(filesystem_dir) +SUBDIRS = c++98 c++11 c++17 $(filesystem_dir) # Cross compiler support. if VTV_CYGMIN @@ -58,6 +58,7 @@ endif vpath % $(top_srcdir)/src/c++98 vpath % $(top_srcdir)/src/c++11 +vpath % $(top_srcdir)/src/c++17 if ENABLE_FILESYSTEM_TS vpath % $(top_srcdir)/src/filesystem endif @@ -92,13 +93,15 @@ libstdc___la_LIBADD = \ $(GLIBCXX_LIBS) \ $(top_builddir)/libsupc++/libsupc++convenience.la \ $(top_builddir)/src/c++98/libc++98convenience.la \ - $(top_builddir)/src/c++11/libc++11convenience.la + $(top_builddir)/src/c++11/libc++11convenience.la \ + $(top_builddir)/src/c++17/libc++17convenience.la libstdc___la_DEPENDENCIES = \ ${version_dep} \ $(top_builddir)/libsupc++/libsupc++convenience.la \ $(top_builddir)/src/c++98/libc++98convenience.la \ - $(top_builddir)/src/c++11/libc++11convenience.la + $(top_builddir)/src/c++11/libc++11convenience.la \ + $(top_builddir)/src/c++17/libc++17convenience.la libstdc___la_LDFLAGS = \ -version-info $(libtool_VERSION) ${version_arg} -lm @@ -148,8 +151,8 @@ compatibility-condvar.o: compatibility-condvar.cc # Thus, the shared libs have more compat symbols, which can be found # segregated in the sources with -D_GLIBCXX_SHARED. # -# In the sub-directories of libsupc++, src/c++98, src/c++11, only -# -prefer-pic objects are generated for the convenience libraries. +# In the sub-directories of libsupc++, src/c++98, src/c++11, src/c++17, +# only -prefer-pic objects are generated for the convenience libraries. # # In the main src directory, make shared and static objects just for # the compat libraries. Shared objects are compiled with -prefer-pic diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index d427ed539da..901533e528b 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -152,7 +152,7 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = c++98 c++11 filesystem +DIST_SUBDIRS = c++98 c++11 c++17 filesystem ABI_TWEAKS_SRCDIR = @ABI_TWEAKS_SRCDIR@ ACLOCAL = @ACLOCAL@ ALLOCATOR_H = @ALLOCATOR_H@ @@ -379,7 +379,7 @@ WARN_CXXFLAGS = \ AM_CPPFLAGS = $(GLIBCXX_INCLUDES) $(CPPFLAGS) @ENABLE_FILESYSTEM_TS_FALSE@filesystem_dir = @ENABLE_FILESYSTEM_TS_TRUE@filesystem_dir = filesystem -SUBDIRS = c++98 c++11 $(filesystem_dir) +SUBDIRS = c++98 c++11 c++17 $(filesystem_dir) @VTV_CYGMIN_FALSE@toolexeclib_LTLIBRARIES = libstdc++.la # Cross compiler support. @@ -419,13 +419,15 @@ libstdc___la_LIBADD = \ $(GLIBCXX_LIBS) \ $(top_builddir)/libsupc++/libsupc++convenience.la \ $(top_builddir)/src/c++98/libc++98convenience.la \ - $(top_builddir)/src/c++11/libc++11convenience.la + $(top_builddir)/src/c++11/libc++11convenience.la \ + $(top_builddir)/src/c++17/libc++17convenience.la libstdc___la_DEPENDENCIES = \ ${version_dep} \ $(top_builddir)/libsupc++/libsupc++convenience.la \ $(top_builddir)/src/c++98/libc++98convenience.la \ - $(top_builddir)/src/c++11/libc++11convenience.la + $(top_builddir)/src/c++11/libc++11convenience.la \ + $(top_builddir)/src/c++17/libc++17convenience.la libstdc___la_LDFLAGS = \ -version-info $(libtool_VERSION) ${version_arg} -lm @@ -440,8 +442,8 @@ libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS) # Thus, the shared libs have more compat symbols, which can be found # segregated in the sources with -D_GLIBCXX_SHARED. # -# In the sub-directories of libsupc++, src/c++98, src/c++11, only -# -prefer-pic objects are generated for the convenience libraries. +# In the sub-directories of libsupc++, src/c++98, src/c++11, src/c++17, +# only -prefer-pic objects are generated for the convenience libraries. # # In the main src directory, make shared and static objects just for # the compat libraries. Shared objects are compiled with -prefer-pic @@ -900,6 +902,7 @@ uninstall-am: uninstall-toolexeclibLTLIBRARIES vpath % $(top_srcdir)/src/c++98 vpath % $(top_srcdir)/src/c++11 +vpath % $(top_srcdir)/src/c++17 @ENABLE_FILESYSTEM_TS_TRUE@vpath % $(top_srcdir)/src/filesystem # Use special rules for compatibility-ldbl.cc compilation, as we need to diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index 91bf6f8d642..a22258782cb 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -1,4 +1,4 @@ -## Makefile for the C++03 sources of the GNU C++ Standard library. +## Makefile for the C++11 sources of the GNU C++ Standard library. ## ## Copyright (C) 1997-2018 Free Software Foundation, Inc. ## diff --git a/libstdc++-v3/src/c++17/Makefile.am b/libstdc++-v3/src/c++17/Makefile.am new file mode 100644 index 00000000000..21b64b52dc2 --- /dev/null +++ b/libstdc++-v3/src/c++17/Makefile.am @@ -0,0 +1,111 @@ +## Makefile for the C++17 sources of the GNU C++ Standard library. +## +## Copyright (C) 1997-2018 Free Software Foundation, Inc. +## +## This file is part of the libstdc++ version 3 distribution. +## Process this file with automake to produce Makefile.in. + +## This file is part of the GNU ISO C++ Library. This library is free +## software; you can redistribute it and/or modify it under the +## terms of the GNU General Public License as published by the +## Free Software Foundation; either version 3, or (at your option) +## any later version. + +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License along +## with this library; see the file COPYING3. If not see +## . + +include $(top_srcdir)/fragment.am + +# Convenience library for C++17 runtime. +noinst_LTLIBRARIES = libc++17convenience.la + +headers = + +sources = \ + memory_resource.cc + +if ENABLE_DUAL_ABI +extra_string_inst_sources = +else +extra_string_inst_sources = +endif + +if ENABLE_EXTERN_TEMPLATE +# XTEMPLATE_FLAGS = -fno-implicit-templates +inst_sources = \ + $(extra_string_inst_sources) +else +# XTEMPLATE_FLAGS = +inst_sources = +endif + +vpath % $(top_srcdir)/src/c++17 + +libc__17convenience_la_SOURCES = $(sources) $(inst_sources) + +# AM_CXXFLAGS needs to be in each subdirectory so that it can be +# modified in a per-library or per-sub-library way. Need to manually +# set this option because CONFIG_CXXFLAGS has to be after +# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden +# as the occasion calls for it. +AM_CXXFLAGS = \ + -std=gnu++17 \ + $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ + $(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \ + $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) + +AM_MAKEFLAGS = \ + "gxx_include_dir=$(gxx_include_dir)" + +# Libtool notes + +# 1) In general, libtool expects an argument such as `--tag=CXX' when +# using the C++ compiler, because that will enable the settings +# detected when C++ support was being configured. However, when no +# such flag is given in the command line, libtool attempts to figure +# it out by matching the compiler name in each configuration section +# against a prefix of the command line. The problem is that, if the +# compiler name and its initial flags stored in the libtool +# configuration file don't match those in the command line, libtool +# can't decide which configuration to use, and it gives up. The +# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe +# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to +# attempt to infer which configuration to use. +# +# The second tag argument, `--tag disable-shared` means that libtool +# only compiles each source once, for static objects. In actuality, +# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to +# the libtool command that is used create the object, which is +# suitable for shared libraries. The `--tag disable-shared` must be +# placed after --tag CXX lest things CXX undo the affect of +# disable-shared. + +# 2) Need to explicitly set LTCXXCOMPILE so that EXTRA_CXX_FLAGS is +# last. (That way, things like -O2 passed down from the toplevel can +# be overridden by --enable-debug.) +LTCXXCOMPILE = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(TOPLEVEL_INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(EXTRA_CXX_FLAGS) + +LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) + +# 3) We'd have a problem when building the shared libstdc++ object if +# the rules automake generates would be used. We cannot allow g++ to +# be used since this would add -lstdc++ to the link line which of +# course is problematic at this point. So, we get the top-level +# directory to configure libstdc++-v3 to use gcc as the C++ +# compilation driver. +CXXLINK = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXX) \ + $(VTV_CXXLINKFLAGS) \ + $(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@ diff --git a/libstdc++-v3/src/c++17/Makefile.in b/libstdc++-v3/src/c++17/Makefile.in new file mode 100644 index 00000000000..40b186e0a77 --- /dev/null +++ b/libstdc++-v3/src/c++17/Makefile.in @@ -0,0 +1,654 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(top_srcdir)/fragment.am $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am +subdir = src/c++17 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ + $(top_srcdir)/../config/enable.m4 \ + $(top_srcdir)/../config/futex.m4 \ + $(top_srcdir)/../config/hwcaps.m4 \ + $(top_srcdir)/../config/iconv.m4 \ + $(top_srcdir)/../config/lead-dot.m4 \ + $(top_srcdir)/../config/lib-ld.m4 \ + $(top_srcdir)/../config/lib-link.m4 \ + $(top_srcdir)/../config/lib-prefix.m4 \ + $(top_srcdir)/../config/lthostflags.m4 \ + $(top_srcdir)/../config/multi.m4 \ + $(top_srcdir)/../config/no-executables.m4 \ + $(top_srcdir)/../config/override.m4 \ + $(top_srcdir)/../config/stdint.m4 \ + $(top_srcdir)/../config/unwind_ipinfo.m4 \ + $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ + $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ + $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/crossconfig.m4 \ + $(top_srcdir)/linkage.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/../config/gc++filt.m4 \ + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../config/gthr.m4 \ + $(top_srcdir)/../config/cet.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libc__17convenience_la_LIBADD = +am__objects_1 = memory_resource.lo +am__objects_2 = +@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_3 = $(am__objects_2) +am_libc__17convenience_la_OBJECTS = $(am__objects_1) $(am__objects_3) +libc__17convenience_la_OBJECTS = $(am_libc__17convenience_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +SOURCES = $(libc__17convenience_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +ABI_TWEAKS_SRCDIR = @ABI_TWEAKS_SRCDIR@ +ACLOCAL = @ACLOCAL@ +ALLOCATOR_H = @ALLOCATOR_H@ +ALLOCATOR_NAME = @ALLOCATOR_NAME@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@ +ATOMIC_FLAGS = @ATOMIC_FLAGS@ +ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASIC_FILE_CC = @BASIC_FILE_CC@ +BASIC_FILE_H = @BASIC_FILE_H@ +CC = @CC@ +CCODECVT_CC = @CCODECVT_CC@ +CCOLLATE_CC = @CCOLLATE_CC@ +CCTYPE_CC = @CCTYPE_CC@ +CFLAGS = @CFLAGS@ +CLOCALE_CC = @CLOCALE_CC@ +CLOCALE_H = @CLOCALE_H@ +CLOCALE_INTERNAL_H = @CLOCALE_INTERNAL_H@ +CMESSAGES_CC = @CMESSAGES_CC@ +CMESSAGES_H = @CMESSAGES_H@ +CMONEY_CC = @CMONEY_CC@ +CNUMERIC_CC = @CNUMERIC_CC@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPU_DEFINES_SRCDIR = @CPU_DEFINES_SRCDIR@ +CPU_OPT_BITS_RANDOM = @CPU_OPT_BITS_RANDOM@ +CPU_OPT_EXT_RANDOM = @CPU_OPT_EXT_RANDOM@ +CSTDIO_H = @CSTDIO_H@ +CTIME_CC = @CTIME_CC@ +CTIME_H = @CTIME_H@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFILT = @CXXFILT@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +C_INCLUDE_DIR = @C_INCLUDE_DIR@ +DBLATEX = @DBLATEX@ +DEBUG_FLAGS = @DEBUG_FLAGS@ +DEFS = @DEFS@ +DOT = @DOT@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +EXTRA_CXX_FLAGS = @EXTRA_CXX_FLAGS@ +FGREP = @FGREP@ +GLIBCXX_INCLUDES = @GLIBCXX_INCLUDES@ +GLIBCXX_LIBS = @GLIBCXX_LIBS@ +GREP = @GREP@ +HWCAP_CFLAGS = @HWCAP_CFLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LONG_DOUBLE_COMPAT_FLAGS = @LONG_DOUBLE_COMPAT_FLAGS@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPTIMIZE_CXXFLAGS = @OPTIMIZE_CXXFLAGS@ +OPT_LDFLAGS = @OPT_LDFLAGS@ +OS_INC_SRCDIR = @OS_INC_SRCDIR@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PDFLATEX = @PDFLATEX@ +RANLIB = @RANLIB@ +SECTION_FLAGS = @SECTION_FLAGS@ +SECTION_LDFLAGS = @SECTION_LDFLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYMVER_FILE = @SYMVER_FILE@ +TOPLEVEL_INCLUDES = @TOPLEVEL_INCLUDES@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +VTV_CXXFLAGS = @VTV_CXXFLAGS@ +VTV_CXXLINKFLAGS = @VTV_CXXLINKFLAGS@ +VTV_PCH_CXXFLAGS = @VTV_PCH_CXXFLAGS@ +WARN_FLAGS = @WARN_FLAGS@ +WERROR = @WERROR@ +XMLLINT = @XMLLINT@ +XSLTPROC = @XSLTPROC@ +XSL_STYLE_DIR = @XSL_STYLE_DIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +baseline_dir = @baseline_dir@ +baseline_subdir_switch = @baseline_subdir_switch@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +check_msgfmt = @check_msgfmt@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ +exec_prefix = @exec_prefix@ +get_gcc_base_ver = @get_gcc_base_ver@ +glibcxx_MOFILES = @glibcxx_MOFILES@ +glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@ +glibcxx_POFILES = @glibcxx_POFILES@ +glibcxx_builddir = @glibcxx_builddir@ +glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@ +glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@ +glibcxx_cxx98_abi = @glibcxx_cxx98_abi@ +glibcxx_localedir = @glibcxx_localedir@ +glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@ +glibcxx_prefixdir = @glibcxx_prefixdir@ +glibcxx_srcdir = @glibcxx_srcdir@ +glibcxx_toolexecdir = @glibcxx_toolexecdir@ +glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@ +gxx_include_dir = @gxx_include_dir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libtool_VERSION = @libtool_VERSION@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_host_flags = @lt_host_flags@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +multi_basedir = @multi_basedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +port_specific_symbol_files = @port_specific_symbol_files@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +python_mod_dir = @python_mod_dir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +thread_header = @thread_header@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +toplevel_builddir = @toplevel_builddir@ +toplevel_srcdir = @toplevel_srcdir@ + +# May be used by various substitution variables. +gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) +MAINT_CHARSET = latin1 +mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs +PWD_COMMAND = $${PWDCMD-pwd} +STAMP = echo timestamp > +toolexecdir = $(glibcxx_toolexecdir) +toolexeclibdir = $(glibcxx_toolexeclibdir) +@ENABLE_WERROR_FALSE@WERROR_FLAG = +@ENABLE_WERROR_TRUE@WERROR_FLAG = $(WERROR) +@ENABLE_EXTERN_TEMPLATE_FALSE@XTEMPLATE_FLAGS = +@ENABLE_EXTERN_TEMPLATE_TRUE@XTEMPLATE_FLAGS = -fno-implicit-templates + +# These bits are all figured out from configure. Look in acinclude.m4 +# or configure.ac to see how they are set. See GLIBCXX_EXPORT_FLAGS. +CONFIG_CXXFLAGS = \ + $(SECTION_FLAGS) $(HWCAP_CFLAGS) -frandom-seed=$@ + +WARN_CXXFLAGS = \ + $(WARN_FLAGS) $(WERROR_FLAG) -fdiagnostics-show-location=once + + +# -I/-D flags to pass when compiling. +AM_CPPFLAGS = $(GLIBCXX_INCLUDES) $(CPPFLAGS) + +# Convenience library for C++17 runtime. +noinst_LTLIBRARIES = libc++17convenience.la +headers = +sources = \ + memory_resource.cc + +@ENABLE_DUAL_ABI_FALSE@extra_string_inst_sources = +@ENABLE_DUAL_ABI_TRUE@extra_string_inst_sources = +# XTEMPLATE_FLAGS = +@ENABLE_EXTERN_TEMPLATE_FALSE@inst_sources = + +# XTEMPLATE_FLAGS = -fno-implicit-templates +@ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources = \ +@ENABLE_EXTERN_TEMPLATE_TRUE@ $(extra_string_inst_sources) + +libc__17convenience_la_SOURCES = $(sources) $(inst_sources) + +# AM_CXXFLAGS needs to be in each subdirectory so that it can be +# modified in a per-library or per-sub-library way. Need to manually +# set this option because CONFIG_CXXFLAGS has to be after +# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden +# as the occasion calls for it. +AM_CXXFLAGS = \ + -std=gnu++17 \ + $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ + $(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \ + $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) + +AM_MAKEFLAGS = \ + "gxx_include_dir=$(gxx_include_dir)" + + +# Libtool notes + +# 1) In general, libtool expects an argument such as `--tag=CXX' when +# using the C++ compiler, because that will enable the settings +# detected when C++ support was being configured. However, when no +# such flag is given in the command line, libtool attempts to figure +# it out by matching the compiler name in each configuration section +# against a prefix of the command line. The problem is that, if the +# compiler name and its initial flags stored in the libtool +# configuration file don't match those in the command line, libtool +# can't decide which configuration to use, and it gives up. The +# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe +# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to +# attempt to infer which configuration to use. +# +# The second tag argument, `--tag disable-shared` means that libtool +# only compiles each source once, for static objects. In actuality, +# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to +# the libtool command that is used create the object, which is +# suitable for shared libraries. The `--tag disable-shared` must be +# placed after --tag CXX lest things CXX undo the affect of +# disable-shared. + +# 2) Need to explicitly set LTCXXCOMPILE so that EXTRA_CXX_FLAGS is +# last. (That way, things like -O2 passed down from the toplevel can +# be overridden by --enable-debug.) +LTCXXCOMPILE = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(TOPLEVEL_INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(EXTRA_CXX_FLAGS) + +LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) + +# 3) We'd have a problem when building the shared libstdc++ object if +# the rules automake generates would be used. We cannot allow g++ to +# be used since this would add -lstdc++ to the link line which of +# course is problematic at this point. So, we get the top-level +# directory to configure libstdc++-v3 to use gcc as the C++ +# compilation driver. +CXXLINK = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXX) \ + $(VTV_CXXLINKFLAGS) \ + $(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@ + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/fragment.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps src/c++17/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps src/c++17/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/fragment.am: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libc++17convenience.la: $(libc__17convenience_la_OBJECTS) $(libc__17convenience_la_DEPENDENCIES) $(EXTRA_libc__17convenience_la_DEPENDENCIES) + $(CXXLINK) $(libc__17convenience_la_OBJECTS) $(libc__17convenience_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cc.o: + $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: + $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +vpath % $(top_srcdir)/src/c++17 + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc new file mode 100644 index 00000000000..dd418c1b1aa --- /dev/null +++ b/libstdc++-v3/src/c++17/memory_resource.cc @@ -0,0 +1,111 @@ +// implementation -*- C++ -*- + +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace pmr +{ + namespace + { + class newdel_res_t final : public memory_resource + { + void* + do_allocate(size_t __bytes, size_t __alignment) override + { return ::operator new(__bytes, std::align_val_t(__alignment)); } + + void + do_deallocate(void* __p, size_t __bytes, size_t __alignment) noexcept + override + { ::operator delete(__p, __bytes, std::align_val_t(__alignment)); } + + bool + do_is_equal(const memory_resource& __other) const noexcept override + { return &__other == this; } + }; + + class null_res_t final : public memory_resource + { + void* + do_allocate(size_t, size_t) override + { std::__throw_bad_alloc(); } + + void + do_deallocate(void*, size_t, size_t) noexcept override + { } + + bool + do_is_equal(const memory_resource& __other) const noexcept override + { return &__other == this; } + }; + + template + struct constant_init + { + union { + unsigned char unused; + T obj; + }; + constexpr constant_init() : obj() { } + + template + explicit constexpr constant_init(U arg) : obj(arg) { } + + ~constant_init() { /* do nothing, union member is not destroyed */ } + }; + + constant_init newdel_res{}; + constant_init null_res{}; + constant_init> default_res{&newdel_res.obj}; + } // namespace + + memory_resource* + new_delete_resource() noexcept + { return &newdel_res.obj; } + + memory_resource* + null_memory_resource() noexcept + { return &null_res.obj; } + + memory_resource* + set_default_resource(memory_resource* r) noexcept + { + if (r == nullptr) + r = new_delete_resource(); + return default_res.obj.exchange(r); + } + + memory_resource* + get_default_resource() noexcept + { return default_res.obj.load(); } + +} // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + + diff --git a/libstdc++-v3/testsuite/20_util/memory_resource/1.cc b/libstdc++-v3/testsuite/20_util/memory_resource/1.cc new file mode 100644 index 00000000000..d848374e71a --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/memory_resource/1.cc @@ -0,0 +1,47 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++17 } } + +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +static_assert(std::is_abstract_v); +static_assert(std::is_polymorphic_v); +static_assert(!std::is_final_v); + +struct R0 : std::pmr::memory_resource { }; +static_assert(std::is_abstract_v); + +struct R1 : R0 { + void* do_allocate(std::size_t, std::size_t) override; +}; +static_assert(std::is_abstract_v); + +struct R2 : R1 { + void do_deallocate(void*, std::size_t, std::size_t) override; +}; +static_assert(std::is_abstract_v); + +struct R3 : R2 { + bool do_is_equal(const std::pmr::memory_resource&) const noexcept override; +}; +static_assert(!std::is_abstract_v); +static_assert(std::is_default_constructible_v); +static_assert(std::is_copy_constructible_v); +static_assert(std::is_copy_assignable_v); +static_assert(std::is_destructible_v); diff --git a/libstdc++-v3/testsuite/20_util/memory_resource/2.cc b/libstdc++-v3/testsuite/20_util/memory_resource/2.cc new file mode 100644 index 00000000000..b99aa49fce1 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/memory_resource/2.cc @@ -0,0 +1,112 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } +// { dg-skip-if "" { *-*-* } { -fno-aligned-new } } + +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +struct R : std::pmr::memory_resource { + void* do_allocate(std::size_t, std::size_t) override; + void do_deallocate(void*, std::size_t, std::size_t) override; + bool do_is_equal(const std::pmr::memory_resource&) const noexcept override; +}; + +bool called = false; + +void* R::do_allocate(std::size_t bytes, std::size_t a) +{ + called = true; + return ::operator new(bytes, std::align_val_t(a)); +} + +void R::do_deallocate(void* p, std::size_t bytes, std::size_t a) +{ + called = true; + ::operator delete(p, bytes, std::align_val_t(a)); +} + +bool R::do_is_equal(const std::pmr::memory_resource& r) const noexcept +{ + called = true; + return this == &r; +} + +void +test01() +{ + R res; + called = false; + auto p = res.allocate(1, 1); + VERIFY( called ); + called = false; + res.deallocate(p, 1, 1); + VERIFY( called ); + called = false; + VERIFY( res == res ); + VERIFY( !called ); + VERIFY( ! (res != res) ); + VERIFY( !called ); + + struct X { int i = 0; }; + struct MultipleInheritance : X, R { }; + MultipleInheritance m; + VERIFY( m == m ); + VERIFY( !called ); + VERIFY( ! (m != m) ); + VERIFY( !called ); + VERIFY( m.is_equal(m) ); + VERIFY( called ); + called = false; + VERIFY( ! (m == res) ); + VERIFY( called ); + called = false; + VERIFY( m != res ); + VERIFY( called ); + called = false; + VERIFY( ! (res == m) ); + VERIFY( called ); + called = false; + VERIFY( res != m ); + VERIFY( called ); + called = false; +} + +void +test02() +{ + __gnu_test::memory_resource r1, r2; + VERIFY( r1 == r1 ); + VERIFY( ! (r1 != r1) ); + VERIFY( r1.is_equal(r1) ); + VERIFY( r2 == r2 ); + VERIFY( r2.is_equal(r2) ); + VERIFY( ! (r1 == r2) ); + VERIFY( r1 != r2 ); + VERIFY( ! r1.is_equal(r2) ); + VERIFY( ! (r2 == r1) ); + VERIFY( r2 != r1 ); + VERIFY( ! r2.is_equal(r1) ); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/1.cc b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/1.cc new file mode 100644 index 00000000000..77fa38edbd8 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/1.cc @@ -0,0 +1,53 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++17 } } + +#include + +using std::pmr::monotonic_buffer_resource; +using std::pmr::memory_resource; +using std::size_t; + +static_assert(std::is_base_of_v); +static_assert(!std::is_abstract_v); + +static_assert(std::is_default_constructible_v); +static_assert(std::is_destructible_v); +static_assert(!std::is_copy_constructible_v); +static_assert(!std::is_copy_assignable_v); +static_assert(!std::is_move_constructible_v); +static_assert(!std::is_move_assignable_v); + +static_assert(std::is_constructible_v); +static_assert(std::is_constructible_v); +static_assert(std::is_constructible_v); + +static_assert(std::is_constructible_v); +static_assert(std::is_constructible_v); + +// Unary constructors are explicit. +static_assert(!std::is_convertible_v); +static_assert(!std::is_convertible_v); diff --git a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc new file mode 100644 index 00000000000..d1c2715ef8d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc @@ -0,0 +1,221 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +#include +#include + +void +test01() +{ + __gnu_test::memory_resource r; + + // test that it's possible to allocate after each of the constructors + { + std::pmr::monotonic_buffer_resource mr(&r); + auto p = mr.allocate(1024); + VERIFY( p != nullptr ); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + } + VERIFY( r.number_of_active_allocations() == 0 ); + { + std::pmr::monotonic_buffer_resource mr(128, &r); + auto p = mr.allocate(1024); + VERIFY( p != nullptr ); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + } + VERIFY( r.number_of_active_allocations() == 0 ); + { + unsigned char buf[64]; + std::pmr::monotonic_buffer_resource mr((void*)buf, sizeof(buf), &r); + auto p = mr.allocate(1024); + VERIFY( p != nullptr ); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + } + VERIFY( r.number_of_active_allocations() == 0 ); + { + std::pmr::monotonic_buffer_resource mr; + auto p = mr.allocate(1024); + VERIFY( p != nullptr ); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + } + { + std::pmr::monotonic_buffer_resource mr(64); + auto p = mr.allocate(1024); + VERIFY( p != nullptr ); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + } + { + unsigned char buf[64]; + std::pmr::monotonic_buffer_resource mr((void*)buf, sizeof(buf)); + auto p = mr.allocate(1024); + VERIFY( p != nullptr ); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + } +} + +void +test02() +{ + unsigned char buf[64]; + std::pmr::monotonic_buffer_resource mr(buf, sizeof(buf)); + + auto p = mr.allocate(0); + VERIFY( p != nullptr ); + auto q = mr.allocate(0); + VERIFY( q != nullptr ); + VERIFY( p != q ); + + p = mr.allocate(0, 1); + VERIFY( p != nullptr ); + q = mr.allocate(0, 1); + VERIFY( q != nullptr ); + VERIFY( p != q ); +} + +void +test03() +{ +#if __cpp_exceptions + { + std::pmr::monotonic_buffer_resource mr(std::pmr::null_memory_resource()); + bool caught = false; + try + { + (void) mr.allocate(1, 1); + } + catch (const std::bad_alloc&) + { + caught = true; + } + VERIFY( caught ); + } + { + unsigned char buf[16]; + std::pmr::monotonic_buffer_resource mr(buf, sizeof(buf), + std::pmr::null_memory_resource()); + (void) mr.allocate(16, 1); + bool caught = false; + try + { + (void) mr.allocate(1, 1); + } + catch (const std::bad_alloc&) + { + caught = true; + } + VERIFY( caught ); + } +#endif +} + +void +test04() +{ + auto buf = new unsigned char[512]; + std::pmr::monotonic_buffer_resource mr(buf, 512, + std::pmr::null_memory_resource()); + std::size_t prev_size = 1; + void* prev_ptr = mr.allocate(prev_size, 1); + for (int i = 0; i < 9; ++i) + { + std::size_t size = 1 << i; + void* ptr = mr.allocate(size, 1); + VERIFY( ((char*)ptr - (char*)prev_ptr) == prev_size ); + prev_ptr = ptr; + prev_size = size; + } +} + +void +test05() +{ + // test that returned pointer is correctly aligned + auto is_aligned = [](void* p, size_t alignment) -> bool { + return (reinterpret_cast(p) % alignment) == 0; + }; + + auto buf = new unsigned char[2048]; + std::pmr::monotonic_buffer_resource mr(buf+1, 2047); + for (int i = 0; i < 9; ++i) + { + auto p = mr.allocate(1, 1 << i); + VERIFY( is_aligned(p, 1 << i) ); + // Make next available byte misaligned: + (void) mr.allocate(1 << i, 1); + } +} + +void +test06() +{ + // check for geometric progression in buffer sizes from upstream + + struct resource : __gnu_test::memory_resource + { + bool allocated = false; + std::size_t last_size = 0; + + void* + do_allocate(size_t bytes, size_t align) override + { + allocated = true; + last_size = bytes; + return __gnu_test::memory_resource::do_allocate(bytes, align); + } + }; + + resource r; + std::pmr::monotonic_buffer_resource mr(32, &r); + std::size_t last_size = 0; + + for (int i = 0; i < 100; ++i) + { + (void) mr.allocate(16); + if (r.allocated) + { + VERIFY(r.last_size >= last_size); + last_size = r.last_size; + r.allocated = false; + } + } +} + +int +main() +{ + test01(); + test02(); + test03(); + test04(); + test05(); + test06(); +} diff --git a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/deallocate.cc b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/deallocate.cc new file mode 100644 index 00000000000..427256d672a --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/deallocate.cc @@ -0,0 +1,103 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +#include +#include + +struct resource : __gnu_test::memory_resource +{ + int allocate_calls = 0; + int deallocate_calls = 0; + + void* + do_allocate(std::size_t bytes, std::size_t align) override + { + ++allocate_calls; + return __gnu_test::memory_resource::do_allocate(bytes, align); + } + + void + do_deallocate(void* p, std::size_t bytes, std::size_t align) override + { + ++deallocate_calls; + __gnu_test::memory_resource::do_deallocate(p, bytes, align); + } +}; + +void +test01() +{ + resource r; + + // test that it's possible to deallocate after each of the constructors + { + std::pmr::monotonic_buffer_resource mr(&r); + auto p = mr.allocate(1024); + VERIFY( p != nullptr ); + const std::uintptr_t pi = reinterpret_cast(p); + mr.deallocate(p, 1024); + VERIFY( r.deallocate_calls == 0 ); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( pi != reinterpret_cast(q) ); + mr.deallocate(q, 1024); + VERIFY( r.deallocate_calls == 0 ); + } + VERIFY( r.deallocate_calls == r.allocate_calls ); + VERIFY( r.number_of_active_allocations() == 0 ); + { + r.deallocate_calls = r.allocate_calls = 0; + std::pmr::monotonic_buffer_resource mr(128, &r); + auto p = mr.allocate(64); + VERIFY( p != nullptr ); + const std::uintptr_t pi = reinterpret_cast(p); + mr.deallocate(p, 64); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + VERIFY( pi != reinterpret_cast(q) ); + mr.deallocate(q, 1024); + VERIFY( r.deallocate_calls == 0 ); + } + VERIFY( r.number_of_active_allocations() == 0 ); + { + r.deallocate_calls = r.allocate_calls = 0; + unsigned char buf[64]; + std::pmr::monotonic_buffer_resource mr((void*)buf, sizeof(buf), &r); + auto p = mr.allocate(64); + VERIFY( p != nullptr ); + const std::uintptr_t pi = reinterpret_cast(p); + mr.deallocate(p, 64); + auto q = mr.allocate(1024); + VERIFY( q != nullptr ); + VERIFY( p != q ); + VERIFY( pi != reinterpret_cast(q) ); + mr.deallocate(q, 1024); + VERIFY( r.deallocate_calls == 0 ); + } + VERIFY( r.deallocate_calls == r.allocate_calls ); + VERIFY( r.number_of_active_allocations() == 0 ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/release.cc b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/release.cc new file mode 100644 index 00000000000..0c7f31789e6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/release.cc @@ -0,0 +1,172 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +#include +#include + +struct resource : __gnu_test::memory_resource +{ + int allocate_calls = 0; + int deallocate_calls = 0; + + void* + do_allocate(std::size_t bytes, std::size_t align) override + { + ++allocate_calls; + return __gnu_test::memory_resource::do_allocate(bytes, align); + } + + void + do_deallocate(void* p, std::size_t bytes, std::size_t align) override + { + ++deallocate_calls; + __gnu_test::memory_resource::do_deallocate(p, bytes, align); + } +}; + +void +test01() +{ + resource r; + std::pmr::monotonic_buffer_resource mbr(&r); + auto p = mbr.allocate(10, 16); + mbr.deallocate(p, 1, 2); + VERIFY( r.deallocate_calls == 0 ); + p = mbr.allocate(10, 16); + p = mbr.allocate(10, 16); + p = mbr.allocate(10, 16); + p = mbr.allocate(1024, 64); + p = mbr.allocate(1024, 64); + p = mbr.allocate(128, 8); + p = mbr.allocate(128, 8); + p = mbr.allocate(128, 8); + p = mbr.allocate(128, 8); + p = mbr.allocate(128, 8); + p = mbr.allocate(128, 8); + p = mbr.allocate(128, 8); + mbr.deallocate(p, 1, 2); + p = mbr.allocate(1024, 16); + p = mbr.allocate(1024, 16); + mbr.deallocate(p, 1, 2); + VERIFY( r.deallocate_calls == 0 ); + mbr.release(); + VERIFY( r.deallocate_calls != 0 ); + VERIFY( r.deallocate_calls == r.allocate_calls ); + VERIFY( mbr.upstream_resource() == &r ); + VERIFY( r.number_of_active_allocations() == 0 ); +} + +void +test02() +{ + std::pmr::monotonic_buffer_resource mbr; // uses get_default_resource() + auto* const upstream = mbr.upstream_resource(); + resource r; + __gnu_test::default_resource_mgr _(&r); // calls set_default_resource(&r) + mbr.release(); + // release() doesn't change upstream resource: + VERIFY( mbr.upstream_resource() == upstream ); +} + +void +test03() +{ + resource r; + __gnu_test::default_resource_mgr _(&r); + std::pmr::monotonic_buffer_resource mbr(16); + for (int i = 0; i < 100; ++i) + (void) mbr.allocate(4, 1); + const int allocations = r.allocate_calls; + VERIFY( allocations != 0 ); + mbr.release(); + VERIFY( r.allocate_calls == r.deallocate_calls ); + VERIFY( r.number_of_active_allocations() == 0 ); + + // next_buffer_size should have been reset to the initial value, + // so the allocations from upstream should be the same as before. + r.allocate_calls = 0; + r.deallocate_calls = 0; + for (int i = 0; i < 100; ++i) + (void) mbr.allocate(4,1); + VERIFY( allocations == r.allocate_calls ); +} + +void +test04() +{ + resource r; + unsigned char buffer[1024]; + std::pmr::monotonic_buffer_resource mbr(buffer, sizeof(buffer), &r); + void* p = mbr.allocate(800, 16); + VERIFY( p == buffer ); + VERIFY( r.allocate_calls == 0 ); + p = mbr.allocate(300, 1); + VERIFY( p != buffer ); + VERIFY( r.allocate_calls == 1 ); + mbr.release(); + VERIFY( r.deallocate_calls == 1 ); + VERIFY( mbr.upstream_resource() == &r ); + VERIFY( r.number_of_active_allocations() == 0 ); + // initial buffer should be used again now: + p = mbr.allocate(1000); + VERIFY( p == buffer ); + VERIFY( r.allocate_calls == 1 ); +} + +void +test05() // LWG 3120 +{ + char buffer[100]; + { + std::pmr::monotonic_buffer_resource mr(buffer, sizeof(buffer), + std::pmr::null_memory_resource()); + mr.release(); + (void) mr.allocate(60); + } + + { + std::pmr::monotonic_buffer_resource mr(buffer, sizeof(buffer), + std::pmr::null_memory_resource()); + (void) mr.allocate(60); + mr.release(); + (void) mr.allocate(60); + } + + { + resource r; + std::pmr::monotonic_buffer_resource mr(&r); + for (int i = 0; i < 100; ++i) + { + (void) mr.allocate(1); + mr.release(); + } + VERIFY( r.number_of_active_allocations() == 0 ); + } +} + +int +main() +{ + test01(); + test02(); + test03(); + test04(); + test05(); +} diff --git a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/upstream_resource.cc b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/upstream_resource.cc new file mode 100644 index 00000000000..c09294f4272 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/upstream_resource.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +#include +#include + +void +test01() +{ + __gnu_test::memory_resource r; + const auto null = std::pmr::null_memory_resource(); + const auto newdel = std::pmr::new_delete_resource(); + std::pmr::set_default_resource(null); + + { + std::pmr::monotonic_buffer_resource mr(&r); + VERIFY( mr.upstream_resource() == &r ); + __gnu_test::default_resource_mgr _(newdel); + VERIFY( mr.upstream_resource() == &r ); + } + { + std::pmr::monotonic_buffer_resource mr(128, &r); + VERIFY( mr.upstream_resource() == &r ); + __gnu_test::default_resource_mgr _(newdel); + VERIFY( mr.upstream_resource() == &r ); + } + { + unsigned char buf[64]; + std::pmr::monotonic_buffer_resource mr((void*)buf, sizeof(buf), &r); + VERIFY( mr.upstream_resource() == &r ); + __gnu_test::default_resource_mgr _(newdel); + VERIFY( mr.upstream_resource() == &r ); + } + { + std::pmr::monotonic_buffer_resource mr; + VERIFY( mr.upstream_resource() == null ); + __gnu_test::default_resource_mgr _(newdel); + VERIFY( mr.upstream_resource() == null ); + } + { + std::pmr::monotonic_buffer_resource mr(64); + VERIFY( mr.upstream_resource() == null ); + __gnu_test::default_resource_mgr _(newdel); + VERIFY( mr.upstream_resource() == null ); + } + { + unsigned char buf[64]; + std::pmr::monotonic_buffer_resource mr((void*)buf, sizeof(buf)); + VERIFY( mr.upstream_resource() == null ); + __gnu_test::default_resource_mgr _(newdel); + VERIFY( mr.upstream_resource() == null ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/polymorphic_allocator/1.cc b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/1.cc new file mode 100644 index 00000000000..4bc7f79e2b6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/1.cc @@ -0,0 +1,36 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++17 } } + +#include + +struct X { int i = 0; }; + +using test_type = std::pmr::polymorphic_allocator; + +static_assert(std::is_default_constructible_v); +static_assert(std::is_destructible_v); +static_assert(std::is_copy_constructible_v); +static_assert(!std::is_copy_assignable_v); +static_assert(std::is_constructible_v); + +static_assert(std::is_same_v); + +static_assert(!std::is_polymorphic_v); +static_assert(!std::is_final_v); diff --git a/libstdc++-v3/testsuite/20_util/polymorphic_allocator/resource.cc b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/resource.cc new file mode 100644 index 00000000000..01f6ace2d80 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/resource.cc @@ -0,0 +1,87 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } +// { dg-skip-if "" { *-*-* } { -fno-aligned-new } } + +#include +#include + +struct X { int i = 0; }; + +using test_type = std::pmr::polymorphic_allocator; + +void +test01() +{ + __gnu_test::memory_resource r; + test_type a(&r), b(&r); + VERIFY( a == a ); + VERIFY( ! (a != a) ); + VERIFY( a == b ); + VERIFY( ! (a != b) ); + VERIFY( a.resource() == &r ); + VERIFY( a.resource() == b.resource() ); + + __gnu_test::memory_resource r2(r); + test_type c(&r2); + VERIFY( c.resource() == &r2 ); + VERIFY( c.resource() != a.resource() ); + VERIFY( c == a ); +} + +void +test02() +{ + __gnu_test::memory_resource r1, r2; + test_type a(&r1), b(&r2); + VERIFY( a == a ); + VERIFY( b == b ); + VERIFY( ! (a == b) ); + VERIFY( ! (b == a) ); + VERIFY( a != b ); + VERIFY( b != a ); + VERIFY( a.resource() == &r1 ); + VERIFY( a.resource() != b.resource() ); + + test_type c; + VERIFY( c == c ); + VERIFY( ! (a == c) ); + VERIFY( ! (c == a) ); + VERIFY( ! (b == c) ); + VERIFY( ! (c == b) ); + VERIFY( a.resource() != c.resource() ); + VERIFY( c.resource() == std::pmr::get_default_resource() ); + + std::pmr::set_default_resource(&r1); + VERIFY( c.resource() != &r1 ); + + test_type d; + VERIFY( d.resource() == &r1 ); + VERIFY( d != c ); + VERIFY( d == a ); + + std::pmr::set_default_resource(nullptr); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/20_util/polymorphic_allocator/select.cc b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/select.cc new file mode 100644 index 00000000000..e5790c03223 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/select.cc @@ -0,0 +1,58 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } +// { dg-skip-if "" { *-*-* } { -fno-aligned-new } } + +#include +#include + +struct X { int i = 0; }; + +using test_type = std::pmr::polymorphic_allocator; + +void +test01() +{ + test_type a, b; + VERIFY( a.select_on_container_copy_construction() == a ); + VERIFY( a.select_on_container_copy_construction() == b ); + + __gnu_test::memory_resource r; + test_type c(&r); + VERIFY( c.select_on_container_copy_construction() != c ); + VERIFY( c.select_on_container_copy_construction() == a ); +} + +void +test02() +{ + __gnu_test::memory_resource r; + test_type a(&r); + VERIFY( a.select_on_container_copy_construction() != a ); + std::pmr::set_default_resource(&r); + VERIFY( a.select_on_container_copy_construction() == a ); + std::pmr::set_default_resource(nullptr); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index 501a81f2276..03679aad8dc 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -31,6 +31,10 @@ #include #include #include +#if __cplusplus >= 201703L +# include +# include +#endif namespace __gnu_test { @@ -691,7 +695,161 @@ namespace __gnu_test using PointerBase_void::PointerBase_void; typedef Derived pointer; }; -#endif +#endif // C++11 + +#if __cplusplus >= 201703L && __cpp_aligned_new + // A concrete memory_resource, with error checking. + class memory_resource : public std::pmr::memory_resource + { + public: + memory_resource() + : lists(new allocation_lists) + { } + + memory_resource(const memory_resource& r) noexcept + : lists(r.lists) + { lists->refcount++; } + + memory_resource& operator=(const memory_resource&) = delete; + + ~memory_resource() + { + if (lists->refcount-- == 1) + delete lists; // last one out turns out the lights + } + + struct bad_size { }; + struct bad_alignment { }; + struct bad_address { }; + + // Deallocate everything (moving the tracking info to the freed list) + void + deallocate_everything() + { + while (lists->active) + { + auto a = lists->active; + // Intentionally virtual dispatch, to inform derived classes: + this->do_deallocate(a->p, a->bytes, a->alignment); + } + } + + // Clear the freed list + void + forget_freed_allocations() + { lists->forget_allocations(lists->freed); } + + // Count how many allocations have been done and not freed. + std::size_t + number_of_active_allocations() const noexcept + { + std::size_t n = 0; + for (auto a = lists->active; a != nullptr; a = a->next) + ++n; + return n; + } + + protected: + void* + do_allocate(std::size_t bytes, std::size_t alignment) override + { + // TODO perform a single allocation and put the allocation struct + // in the buffer using placement new? It means deallocation won't + // actually return memory to the OS, as it will stay in lists->freed. + // + // TODO adjust the returned pointer to be minimally aligned? + // e.g. if alignment==1 don't return something aligned to 2 bytes. + // Maybe not worth it, at least monotonic_buffer_resource will + // never ask upstream for anything with small alignment. + void* p = ::operator new(bytes, std::align_val_t(alignment)); + lists->active = new allocation{p, bytes, alignment, lists->active}; + return p; + } + + void + do_deallocate(void* p, std::size_t bytes, std::size_t alignment) override + { + allocation** aptr = &lists->active; + while (*aptr) + { + allocation* a = *aptr; + if (p == a->p) + { + if (bytes != a->bytes) + throw bad_size(); + if (alignment != a->alignment) + throw bad_alignment(); + ::operator delete(p, bytes, std::align_val_t(alignment)); + *aptr = a->next; + a->next = lists->freed; + lists->freed = a; + return; + } + aptr = &a->next; + } + throw bad_address(); + } + + bool + do_is_equal(const std::pmr::memory_resource& r) const noexcept override + { + // Equality is determined by sharing the same allocation_lists object. + if (auto p = dynamic_cast(&r)) + return p->lists == lists; + return false; + } + + private: + struct allocation + { + void* p; + std::size_t bytes; + std::size_t alignment; + allocation* next; + }; + + // Maintain list of allocated blocks and list of freed blocks. + // Copies of this memory_resource share the same ref-counted lists. + struct allocation_lists + { + unsigned refcount = 1; + allocation* active = nullptr; + allocation* freed = nullptr; + + void forget_allocations(allocation*& list) + { + while (list) + { + auto p = list; + list = list->next; + delete p; + } + } + + ~allocation_lists() + { + forget_allocations(active); // Anything in this list is a leak! + forget_allocations(freed); + } + }; + + allocation_lists* lists; + }; + + // Set the default resource, and restore the previous one on destruction. + struct default_resource_mgr + { + explicit default_resource_mgr(std::pmr::memory_resource* r) + : prev(std::pmr::set_default_resource(r)) + { } + + ~default_resource_mgr() + { std::pmr::set_default_resource(prev); } + + std::pmr::memory_resource* prev; + }; + +#endif // C++17 && aligned-new } // namespace __gnu_test