Add initial version of C++17 <memory_resource> header
authorJonathan Wakely <jwakely@redhat.com>
Tue, 24 Jul 2018 21:09:55 +0000 (22:09 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 24 Jul 2018 21:09:55 +0000 (22:09 +0100)
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
<experimental/memory_resource>, 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 <memory_resource> header.
* include/Makefile.in: Regenerate.
* include/precompiled/stdc++.h: Include <memory_resource> 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

24 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/configure
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/precompiled/stdc++.h
libstdc++-v3/include/std/memory_resource [new file with mode: 0644]
libstdc++-v3/src/Makefile.am
libstdc++-v3/src/Makefile.in
libstdc++-v3/src/c++11/Makefile.am
libstdc++-v3/src/c++17/Makefile.am [new file with mode: 0644]
libstdc++-v3/src/c++17/Makefile.in [new file with mode: 0644]
libstdc++-v3/src/c++17/memory_resource.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/memory_resource/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/memory_resource/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/deallocate.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/release.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/upstream_resource.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/polymorphic_allocator/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/polymorphic_allocator/resource.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/polymorphic_allocator/select.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_allocator.h

index 91c0f4c0afe32ea2b917465ca01f82fe9d04ef75..bef5a97cd6ebbab6e07b6ac5a490a007abbc68bc 100644 (file)
@@ -1,5 +1,39 @@
 2018-07-24  Jonathan Wakely  <jwakely@redhat.com>
 
+       * config/abi/pre/gnu.ver: Export new symbols.
+       * configure: Regenerate.
+       * include/Makefile.am: Add new <memory_resource> header.
+       * include/Makefile.in: Regenerate.
+       * include/precompiled/stdc++.h: Include <memory_resource> 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.
index b09bdef6d09a5c6079e5ca66084b683b2f5cb04b..36459e88b6a46ac5b6b6dfa63adc32d96378b7d0 100644 (file)
@@ -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.
index 101dcd9cb7cbf8722e3f1e00211cd41ad633eb20..54a2e8a380e14ee82e4cb65e45022831976b50c7 100755 (executable)
@@ -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
index d1453a5abce7b5b65057a41ca4a704b5f36a8a9d..9daa8856e708f5b3c532808519206235dc3c6ab1 100644 (file)
@@ -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 \
index ff3249e346ea3e813bb82229be0be069ab3cae9f..a122c9cfe2cf1c5fa56fa1bdd3d0c82e5b0c2100 100644 (file)
@@ -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 \
index 80769233eb3eb45bbe80155fbeaad0b7eb47758c..1f5373540522ebfc6297c54890f4459832fb678f 100644 (file)
 // #include <execution>
 #include <filesystem>
 #include <optional>
-// #include <memory_resource>
+#include <memory_resource>
 #include <string_view>
 #include <variant>
 #endif
diff --git a/libstdc++-v3/include/std/memory_resource b/libstdc++-v3/include/std/memory_resource
new file mode 100644 (file)
index 0000000..b3f8f7d
--- /dev/null
@@ -0,0 +1,510 @@
+// <memory_resource> -*- 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
+// <http://www.gnu.org/licenses/>.
+
+/** @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 <bit>                         // __ceil2, __log2p1
+#include <memory>                      // align, allocator_arg_t, __uses_alloc
+#include <utility>                     // pair, index_sequence
+#include <cstddef>                     // size_t, max_align_t
+#include <debug/assertions.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace pmr
+{
+// #define __cpp_lib_memory_resource 201603
+
+  class memory_resource;
+
+  template<typename _Tp>
+    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<typename _Tp>
+    class polymorphic_allocator
+    {
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2975. Missing case for pair construction in polymorphic allocators
+      template<typename _Up>
+       struct __not_pair { using type = void; };
+
+      template<typename _Up1, typename _Up2>
+       struct __not_pair<pair<_Up1, _Up2>> { };
+
+    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<typename _Up>
+       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<size_t>::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<typename _Tp1, typename... _Args>
+       __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<typename _Tp1, typename _Tp2,
+              typename... _Args1, typename... _Args2>
+       __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<typename _Tp1, typename _Tp2>
+       __attribute__((__nonnull__))
+       void
+       construct(pair<_Tp1, _Tp2>* __p)
+       { this->construct(__p, piecewise_construct, tuple<>(), tuple<>()); }
+
+      template<typename _Tp1, typename _Tp2, typename _Up, typename _Vp>
+       __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 <typename _Tp1, typename _Tp2, typename _Up, typename _Vp>
+       __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<typename _Tp1, typename _Tp2, typename _Up, typename _Vp>
+       __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<typename _Up>
+       __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<polymorphic_allocator>;
+      using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>;
+
+      template<typename _Tp1, typename... _Args>
+       static void
+       _S_construct(__uses_alloc0, _Tp1* __p, _Args&&... __args)
+       { ::new(__p) _Tp1(std::forward<_Args>(__args)...); }
+
+      template<typename _Tp1, typename... _Args>
+       static void
+       _S_construct(__uses_alloc1_ __ua, _Tp1* __p, _Args&&... __args)
+       {
+         ::new(__p) _Tp1(allocator_arg, *__ua._M_a,
+                         std::forward<_Args>(__args)...);
+       }
+
+      template<typename _Tp1, typename... _Args>
+       static void
+       _S_construct(__uses_alloc2_ __ua, _Tp1* __p, _Args&&... __args)
+       { ::new(__p) _Tp1(std::forward<_Args>(__args)..., *__ua._M_a); }
+
+      template<typename _Ind, typename... _Args>
+       static tuple<_Args&&...>
+       _S_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t)
+       { return std::move(__t); }
+
+      template<size_t... _Ind, typename... _Args>
+       static tuple<allocator_arg_t, polymorphic_allocator&, _Args&&...>
+       _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<size_t... _Ind, typename... _Args>
+       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<typename _Tp1, typename _Tp2>
+    inline bool
+    operator==(const polymorphic_allocator<_Tp1>& __a,
+              const polymorphic_allocator<_Tp2>& __b) noexcept
+    { return *__a.resource() == *__b.resource(); }
+
+  template<typename _Tp1, typename _Tp2>
+    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<void*, size_t>
+      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
index ba30dde8fecbef2990f89d12e0729f3727d86b00..09edcdbc471d9fedabe4a2b20b110c79955c8c52 100644 (file)
@@ -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
index d427ed539da4a9e15379030add041dbd18667e05..901533e528b9267b9705b20e0016486f60c0d042 100644 (file)
@@ -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
index 91bf6f8d642d46f6cf336a6bc4ab52b30b82be73..a22258782cb0483bc074ea469690e5d69c5e6f7e 100644 (file)
@@ -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 (file)
index 0000000..21b64b5
--- /dev/null
@@ -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
+## <http://www.gnu.org/licenses/>.
+
+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 (file)
index 0000000..40b186e
--- /dev/null
@@ -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 (file)
index 0000000..dd418c1
--- /dev/null
@@ -0,0 +1,111 @@
+// <memory_resource> 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
+// <http://www.gnu.org/licenses/>.
+
+#include <memory_resource>
+#include <atomic>
+#include <new>
+
+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<typename T>
+      struct constant_init
+      {
+       union {
+         unsigned char unused;
+         T obj;
+       };
+       constexpr constant_init() : obj() { }
+
+       template<typename U>
+         explicit constexpr constant_init(U arg) : obj(arg) { }
+
+       ~constant_init() { /* do nothing, union member is not destroyed */ }
+      };
+
+    constant_init<newdel_res_t> newdel_res{};
+    constant_init<null_res_t> null_res{};
+    constant_init<atomic<memory_resource*>> 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 (file)
index 0000000..d848374
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+#include <memory_resource>
+
+static_assert(std::is_abstract_v<std::pmr::memory_resource>);
+static_assert(std::is_polymorphic_v<std::pmr::memory_resource>);
+static_assert(!std::is_final_v<std::pmr::memory_resource>);
+
+struct R0 : std::pmr::memory_resource { };
+static_assert(std::is_abstract_v<R0>);
+
+struct R1 : R0 {
+  void* do_allocate(std::size_t, std::size_t) override;
+};
+static_assert(std::is_abstract_v<R1>);
+
+struct R2 : R1 {
+  void do_deallocate(void*, std::size_t, std::size_t) override;
+};
+static_assert(std::is_abstract_v<R2>);
+
+struct R3 : R2 {
+  bool do_is_equal(const std::pmr::memory_resource&) const noexcept override;
+};
+static_assert(!std::is_abstract_v<R3>);
+static_assert(std::is_default_constructible_v<R3>);
+static_assert(std::is_copy_constructible_v<R3>);
+static_assert(std::is_copy_assignable_v<R3>);
+static_assert(std::is_destructible_v<R3>);
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 (file)
index 0000000..b99aa49
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+#include <memory_resource>
+#include <testsuite_allocator.h>
+
+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 (file)
index 0000000..77fa38e
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <memory_resource>
+
+using std::pmr::monotonic_buffer_resource;
+using std::pmr::memory_resource;
+using std::size_t;
+
+static_assert(std::is_base_of_v<memory_resource, monotonic_buffer_resource>);
+static_assert(!std::is_abstract_v<monotonic_buffer_resource>);
+
+static_assert(std::is_default_constructible_v<monotonic_buffer_resource>);
+static_assert(std::is_destructible_v<monotonic_buffer_resource>);
+static_assert(!std::is_copy_constructible_v<monotonic_buffer_resource>);
+static_assert(!std::is_copy_assignable_v<monotonic_buffer_resource>);
+static_assert(!std::is_move_constructible_v<monotonic_buffer_resource>);
+static_assert(!std::is_move_assignable_v<monotonic_buffer_resource>);
+
+static_assert(std::is_constructible_v<monotonic_buffer_resource,
+                                     memory_resource*>);
+static_assert(std::is_constructible_v<monotonic_buffer_resource,
+                                     size_t, memory_resource*>);
+static_assert(std::is_constructible_v<monotonic_buffer_resource,
+                                     void*, size_t, memory_resource*>);
+
+static_assert(std::is_constructible_v<monotonic_buffer_resource,
+                                     size_t>);
+static_assert(std::is_constructible_v<monotonic_buffer_resource,
+                                     void*, size_t>);
+
+// Unary constructors are explicit.
+static_assert(!std::is_convertible_v<memory_resource*,
+                                    monotonic_buffer_resource>);
+static_assert(!std::is_convertible_v<size_t,
+                                    monotonic_buffer_resource>);
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 (file)
index 0000000..d1c2715
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+#include <memory_resource>
+#include <testsuite_allocator.h>
+
+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<std::uintptr_t>(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 (file)
index 0000000..427256d
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+#include <memory_resource>
+#include <testsuite_allocator.h>
+
+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<std::uintptr_t>(p);
+    mr.deallocate(p, 1024);
+    VERIFY( r.deallocate_calls == 0 );
+    auto q = mr.allocate(1024);
+    VERIFY( q != nullptr );
+    VERIFY( pi != reinterpret_cast<std::uintptr_t>(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<std::uintptr_t>(p);
+    mr.deallocate(p, 64);
+    auto q = mr.allocate(1024);
+    VERIFY( q != nullptr );
+    VERIFY( p != q );
+    VERIFY( pi != reinterpret_cast<std::uintptr_t>(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<std::uintptr_t>(p);
+    mr.deallocate(p, 64);
+    auto q = mr.allocate(1024);
+    VERIFY( q != nullptr );
+    VERIFY( p != q );
+    VERIFY( pi != reinterpret_cast<std::uintptr_t>(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 (file)
index 0000000..0c7f317
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+#include <memory_resource>
+#include <testsuite_allocator.h>
+
+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 (file)
index 0000000..c09294f
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+#include <memory_resource>
+#include <testsuite_allocator.h>
+
+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 (file)
index 0000000..4bc7f79
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <memory_resource>
+
+struct X { int i = 0; };
+
+using test_type = std::pmr::polymorphic_allocator<X>;
+
+static_assert(std::is_default_constructible_v<test_type>);
+static_assert(std::is_destructible_v<test_type>);
+static_assert(std::is_copy_constructible_v<test_type>);
+static_assert(!std::is_copy_assignable_v<test_type>);
+static_assert(std::is_constructible_v<test_type, std::pmr::memory_resource*>);
+
+static_assert(std::is_same_v<test_type::value_type, X>);
+
+static_assert(!std::is_polymorphic_v<test_type>);
+static_assert(!std::is_final_v<test_type>);
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 (file)
index 0000000..01f6ace
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+// { dg-skip-if "" { *-*-* } { -fno-aligned-new } }
+
+#include <memory_resource>
+#include <testsuite_allocator.h>
+
+struct X { int i = 0; };
+
+using test_type = std::pmr::polymorphic_allocator<X>;
+
+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 (file)
index 0000000..e5790c0
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+// { dg-skip-if "" { *-*-* } { -fno-aligned-new } }
+
+#include <memory_resource>
+#include <testsuite_allocator.h>
+
+struct X { int i = 0; };
+
+using test_type = std::pmr::polymorphic_allocator<X>;
+
+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();
+}
index 501a81f2276d3c4b61c606ade13f2abf4c1ca97f..03679aad8dcd496e514a60fcbc971c3501c1af29 100644 (file)
 #include <ext/pointer.h>
 #include <ext/alloc_traits.h>
 #include <testsuite_hooks.h>
+#if __cplusplus >= 201703L
+# include <memory_resource>
+# include <new>
+#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<const memory_resource*>(&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