public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Ensure pmr aliases work without <memory_resource>
@ 2022-05-19 22:42 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2022-05-19 22:42 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Tested powerpc64le-linux, pushed to trunk.

This adds a lot more code to every container header, which is
unfortunate. I plan to replace the inclusion of <tuple> in the
<bits/memory_resource.h> header with something smaller that just defines
std:tuple, and not all the helpers like std::make_tuple.

-- >8 --

Currently the alias templates for std::pmr::vector, std::pmr::string
etc. are defined using a forward declaration for polymorphic_allocator.
This means you can't actually use the alias templates unless you also
include <memory_resource>. The rationale for that is that it's a fairly
large header, and most users don't need it. This isn't uncontroversial
though, and LWG 3681 questions whether it's even conforming.

This change adds a new <bits/memory_resource.h> header with the minimum
needed to use polymorphic_allocator and the std::pmr container aliases.
Including <memory_resource> is still necessary to use the program-wide
resource objects, or the pool resources or monotonic buffer resource.

libstdc++-v3/ChangeLog:

	* include/Makefile.am: Add new header.
	* include/Makefile.in: Regenerate.
	* include/bits/memory_resource.h: New file.
	* include/std/deque: Include <bits/memory_resource.h>.
	* include/std/forward_list: Likewise.
	* include/std/list: Likewise.
	* include/std/map: Likewise.
	* include/std/memory_resource (pmr::memory_resource): Move to
	new <bits/memory_resource.h> header.
	(pmr::polymorphic_allocator): Likewise.
	* include/std/regex: Likewise.
	* include/std/set: Likewise.
	* include/std/stacktrace: Likewise.
	* include/std/string: Likewise.
	* include/std/unordered_map: Likewise.
	* include/std/unordered_set: Likewise.
	* include/std/vector: Likewise.
	* testsuite/21_strings/basic_string/types/pmr_typedefs.cc:
	Remove <memory_resource> header and check construction.
	* testsuite/23_containers/deque/types/pmr_typedefs.cc: Likewise.
	* testsuite/23_containers/forward_list/pmr_typedefs.cc:
	Likewise.
	* testsuite/23_containers/list/pmr_typedefs.cc: Likewise.
	* testsuite/23_containers/map/pmr_typedefs.cc: Likewise.
	* testsuite/23_containers/multimap/pmr_typedefs.cc: Likewise.
	* testsuite/23_containers/multiset/pmr_typedefs.cc: Likewise.
	* testsuite/23_containers/set/pmr_typedefs.cc: Likewise.
	* testsuite/23_containers/unordered_map/pmr_typedefs.cc:
	Likewise.
	* testsuite/23_containers/unordered_multimap/pmr_typedefs.cc:
	Likewise.
	* testsuite/23_containers/unordered_multiset/pmr_typedefs.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/pmr_typedefs.cc:
	Likewise.
	* testsuite/23_containers/vector/pmr_typedefs.cc: Likewise.
	* testsuite/28_regex/match_results/pmr_typedefs.cc: Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/variadic-tuple.C: Qualify function to avoid ADL
	finding std::make_tuple.
---
 gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C   |   2 +-
 libstdc++-v3/include/Makefile.am              |   1 +
 libstdc++-v3/include/Makefile.in              |   1 +
 libstdc++-v3/include/bits/memory_resource.h   | 507 ++++++++++++++++++
 libstdc++-v3/include/std/deque                |   2 +-
 libstdc++-v3/include/std/forward_list         |   2 +-
 libstdc++-v3/include/std/list                 |   2 +-
 libstdc++-v3/include/std/map                  |   2 +-
 libstdc++-v3/include/std/memory_resource      | 464 +---------------
 libstdc++-v3/include/std/regex                |   2 +-
 libstdc++-v3/include/std/set                  |   2 +-
 libstdc++-v3/include/std/stacktrace           |   2 +-
 libstdc++-v3/include/std/string               |   2 +-
 libstdc++-v3/include/std/unordered_map        |   2 +-
 libstdc++-v3/include/std/unordered_set        |   2 +-
 libstdc++-v3/include/std/vector               |   2 +-
 .../basic_string/types/pmr_typedefs.cc        |   3 +-
 .../23_containers/deque/types/pmr_typedefs.cc |   3 +-
 .../forward_list/pmr_typedefs.cc              |   3 +-
 .../23_containers/list/pmr_typedefs.cc        |   3 +-
 .../23_containers/map/pmr_typedefs.cc         |   3 +-
 .../23_containers/multimap/pmr_typedefs.cc    |   3 +-
 .../23_containers/multiset/pmr_typedefs.cc    |   3 +-
 .../23_containers/set/pmr_typedefs.cc         |   3 +-
 .../unordered_map/pmr_typedefs.cc             |   3 +-
 .../unordered_multimap/pmr_typedefs.cc        |   3 +-
 .../unordered_multiset/pmr_typedefs.cc        |   3 +-
 .../unordered_set/pmr_typedefs.cc             |   3 +-
 .../23_containers/vector/pmr_typedefs.cc      |   3 +-
 .../28_regex/match_results/pmr_typedefs.cc    |   3 +-
 30 files changed, 551 insertions(+), 488 deletions(-)
 create mode 100644 libstdc++-v3/include/bits/memory_resource.h

diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
index b1c6b3d7814..e2699d94ebf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
@@ -272,7 +272,7 @@ int main()
   //  t3a = t3b; DPG: triggers an error, as it should.
 
   tuple<int, float, std::string> t3c = 
-    make_tuple(17, 2.718281828, std::string("Fun"));
+    ::make_tuple(17, 2.718281828, std::string("Fun"));
 
   int seventeen = 17;
   double pi = 3.14159;
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 77eea7d61e8..b46def7ff9f 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -157,6 +157,7 @@ bits_headers = \
 	${bits_srcdir}/localefwd.h \
 	${bits_srcdir}/mask_array.h \
 	${bits_srcdir}/max_size_type.h \
+	${bits_srcdir}/memory_resource.h \
 	${bits_srcdir}/memoryfwd.h \
 	${bits_srcdir}/mofunc_impl.h \
 	${bits_srcdir}/move.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 01bf3e0eb32..f844008a7c5 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -515,6 +515,7 @@ bits_headers = \
 	${bits_srcdir}/localefwd.h \
 	${bits_srcdir}/mask_array.h \
 	${bits_srcdir}/max_size_type.h \
+	${bits_srcdir}/memory_resource.h \
 	${bits_srcdir}/memoryfwd.h \
 	${bits_srcdir}/mofunc_impl.h \
 	${bits_srcdir}/move.h \
diff --git a/libstdc++-v3/include/bits/memory_resource.h b/libstdc++-v3/include/bits/memory_resource.h
new file mode 100644
index 00000000000..d8c7e168235
--- /dev/null
+++ b/libstdc++-v3/include/bits/memory_resource.h
@@ -0,0 +1,507 @@
+// <memory_resource> -*- C++ -*-
+
+// Copyright (C) 2018-2022 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/bits/memory_resource.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{memory_resource}
+ */
+
+#ifndef _GLIBCXX_MEMORY_RESOURCE_H
+#define _GLIBCXX_MEMORY_RESOURCE_H 1
+
+#pragma GCC system_header
+
+#if __cplusplus >= 201703L
+
+#include <new>				// operator new(size_t, void*)
+#include <cstddef>			// size_t, max_align_t, byte
+#include <bits/functexcept.h>		// __throw_bad_array_new_length
+#include <bits/uses_allocator.h>	// allocator_arg_t, __use_alloc
+#include <bits/uses_allocator_args.h>	// uninitialized_construct_using_alloc
+#include <ext/numeric_traits.h>		// __int_traits
+#include <debug/assertions.h>
+
+#if ! __cpp_lib_make_obj_using_allocator
+# include <bits/utility.h>		// index_sequence
+# include <tuple>			// tuple, forward_as_tuple
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace pmr
+{
+  /// 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(); // key function
+
+    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 ::operator new(__bytes, 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); }
+
+    [[nodiscard]]
+    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;
+  };
+
+  [[nodiscard]]
+  inline bool
+  operator==(const memory_resource& __a, const memory_resource& __b) noexcept
+  { return &__a == &__b || __a.is_equal(__b); }
+
+#if __cpp_impl_three_way_comparison < 201907L
+  [[nodiscard]]
+  inline bool
+  operator!=(const memory_resource& __a, const memory_resource& __b) noexcept
+  { return !(__a == __b); }
+#endif
+
+  // 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
+      {
+	extern memory_resource* get_default_resource() noexcept
+	  __attribute__((__returns_nonnull__));
+	_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 ((__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Tp)) < __n)
+	  std::__throw_bad_array_new_length();
+	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)); }
+
+#if __cplusplus > 201703L
+      [[nodiscard]] void*
+      allocate_bytes(size_t __nbytes,
+		     size_t __alignment = alignof(max_align_t))
+      { return _M_resource->allocate(__nbytes, __alignment); }
+
+      void
+      deallocate_bytes(void* __p, size_t __nbytes,
+		       size_t __alignment = alignof(max_align_t))
+      { _M_resource->deallocate(__p, __nbytes, __alignment); }
+
+      template<typename _Up>
+	[[nodiscard]] _Up*
+	allocate_object(size_t __n = 1)
+	{
+	  if ((__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Up)) < __n)
+	    std::__throw_bad_array_new_length();
+	  return static_cast<_Up*>(allocate_bytes(__n * sizeof(_Up),
+						  alignof(_Up)));
+	}
+
+      template<typename _Up>
+	void
+	deallocate_object(_Up* __p, size_t __n = 1)
+	{ deallocate_bytes(__p, __n * sizeof(_Up), alignof(_Up)); }
+
+      template<typename _Up, typename... _CtorArgs>
+	[[nodiscard]] _Up*
+	new_object(_CtorArgs&&... __ctor_args)
+	{
+	  _Up* __p = allocate_object<_Up>();
+	  __try
+	    {
+	      construct(__p, std::forward<_CtorArgs>(__ctor_args)...);
+	    }
+	  __catch (...)
+	    {
+	      deallocate_object(__p);
+	      __throw_exception_again;
+	    }
+	  return __p;
+	}
+
+      template<typename _Up>
+	void
+	delete_object(_Up* __p)
+	{
+	  __p->~_Up();
+	  deallocate_object(__p);
+	}
+#endif // C++2a
+
+#if ! __cpp_lib_make_obj_using_allocator
+      template<typename _Tp1, typename... _Args>
+	__attribute__((__nonnull__))
+	typename __not_pair<_Tp1>::type
+	construct(_Tp1* __p, _Args&&... __args)
+	{
+	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	  // 2969. polymorphic_allocator::construct() shouldn't pass resource()
+	  using __use_tag
+	    = std::__uses_alloc_t<_Tp1, polymorphic_allocator, _Args...>;
+	  if constexpr (is_base_of_v<__uses_alloc0, __use_tag>)
+	    ::new(__p) _Tp1(std::forward<_Args>(__args)...);
+	  else if constexpr (is_base_of_v<__uses_alloc1_, __use_tag>)
+	    ::new(__p) _Tp1(allocator_arg, *this,
+			    std::forward<_Args>(__args)...);
+	  else
+	    ::new(__p) _Tp1(std::forward<_Args>(__args)..., *this);
+	}
+
+      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_i, __x),
+				      _S_construct_p(__y_tag, __y_i, __y));
+	}
+
+      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,
+	      std::forward_as_tuple(std::forward<_Up>(__x)),
+	      std::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,
+	      std::forward_as_tuple(__pr.first),
+	      std::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,
+	      std::forward_as_tuple(std::forward<_Up>(__pr.first)),
+	      std::forward_as_tuple(std::forward<_Vp>(__pr.second)));
+	}
+#else // make_obj_using_allocator
+      template<typename _Tp1, typename... _Args>
+	__attribute__((__nonnull__))
+	void
+	construct(_Tp1* __p, _Args&&... __args)
+	{
+	  std::uninitialized_construct_using_allocator(__p, *this,
+	      std::forward<_Args>(__args)...);
+	}
+#endif
+
+      template<typename _Up>
+	_GLIBCXX20_DEPRECATED_SUGGEST("allocator_traits::destroy")
+	__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; }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3683. operator== for polymorphic_allocator cannot deduce template arg
+      [[nodiscard]]
+      friend bool
+      operator==(const polymorphic_allocator& __a,
+		 const polymorphic_allocator& __b) noexcept
+      { return *__a.resource() == *__b.resource(); }
+
+#if __cpp_impl_three_way_comparison < 201907L
+      [[nodiscard]]
+      friend bool
+      operator!=(const polymorphic_allocator& __a,
+		 const polymorphic_allocator& __b) noexcept
+      { return !(__a == __b); }
+#endif
+
+    private:
+#if ! __cpp_lib_make_obj_using_allocator
+      using __uses_alloc1_ = __uses_alloc1<polymorphic_allocator>;
+      using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>;
+
+      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 }; }
+#endif
+
+      memory_resource* _M_resource;
+    };
+
+  template<typename _Tp1, typename _Tp2>
+    [[nodiscard]]
+    inline bool
+    operator==(const polymorphic_allocator<_Tp1>& __a,
+	       const polymorphic_allocator<_Tp2>& __b) noexcept
+    { return *__a.resource() == *__b.resource(); }
+
+#if __cpp_impl_three_way_comparison < 201907L
+  template<typename _Tp1, typename _Tp2>
+    [[nodiscard]]
+    inline bool
+    operator!=(const polymorphic_allocator<_Tp1>& __a,
+	       const polymorphic_allocator<_Tp2>& __b) noexcept
+    { return !(__a == __b); }
+#endif
+
+} // namespace pmr
+
+  template<typename _Alloc> struct allocator_traits;
+
+  /// Partial specialization for std::pmr::polymorphic_allocator
+  template<typename _Tp>
+    struct allocator_traits<pmr::polymorphic_allocator<_Tp>>
+    {
+      /// The allocator type
+      using allocator_type = pmr::polymorphic_allocator<_Tp>;
+
+      /// The allocated type
+      using value_type = _Tp;
+
+      /// The allocator's pointer type.
+      using pointer = _Tp*;
+
+      /// The allocator's const pointer type.
+      using const_pointer = const _Tp*;
+
+      /// The allocator's void pointer type.
+      using void_pointer = void*;
+
+      /// The allocator's const void pointer type.
+      using const_void_pointer = const void*;
+
+      /// The allocator's difference type
+      using difference_type = std::ptrdiff_t;
+
+      /// The allocator's size type
+      using size_type = std::size_t;
+
+      /** @{
+       * A `polymorphic_allocator` does not propagate when a
+       * container is copied, moved, or swapped.
+       */
+      using propagate_on_container_copy_assignment = false_type;
+      using propagate_on_container_move_assignment = false_type;
+      using propagate_on_container_swap = false_type;
+
+      static allocator_type
+      select_on_container_copy_construction(const allocator_type&) noexcept
+      { return allocator_type(); }
+      /// @}
+
+      /// Whether all instances of the allocator type compare equal.
+      using is_always_equal = false_type;
+
+      template<typename _Up>
+	using rebind_alloc = pmr::polymorphic_allocator<_Up>;
+
+      template<typename _Up>
+	using rebind_traits = allocator_traits<pmr::polymorphic_allocator<_Up>>;
+
+      /**
+       *  @brief  Allocate memory.
+       *  @param  __a  An allocator.
+       *  @param  __n  The number of objects to allocate space for.
+       *
+       *  Calls `a.allocate(n)`.
+      */
+      [[nodiscard]] static pointer
+      allocate(allocator_type& __a, size_type __n)
+      { return __a.allocate(__n); }
+
+      /**
+       *  @brief  Allocate memory.
+       *  @param  __a  An allocator.
+       *  @param  __n  The number of objects to allocate space for.
+       *  @return Memory of suitable size and alignment for `n` objects
+       *          of type `value_type`.
+       *
+       *  The third parameter is ignored..
+       *
+       *  Returns `a.allocate(n)`.
+      */
+      [[nodiscard]] static pointer
+      allocate(allocator_type& __a, size_type __n, const_void_pointer)
+      { return __a.allocate(__n); }
+
+      /**
+       *  @brief  Deallocate memory.
+       *  @param  __a  An allocator.
+       *  @param  __p  Pointer to the memory to deallocate.
+       *  @param  __n  The number of objects space was allocated for.
+       *
+       *  Calls `a.deallocate(p, n)`.
+      */
+      static void
+      deallocate(allocator_type& __a, pointer __p, size_type __n)
+      { __a.deallocate(__p, __n); }
+
+      /**
+       *  @brief  Construct an object of type `_Up`
+       *  @param  __a  An allocator.
+       *  @param  __p  Pointer to memory of suitable size and alignment for
+       *	       an object of type `_Up`.
+       *  @param  __args Constructor arguments.
+       *
+       *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
+       *  in C++11, C++14 and C++17. Changed in C++20 to call
+       *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
+      */
+      template<typename _Up, typename... _Args>
+	static void
+	construct(allocator_type& __a, _Up* __p, _Args&&... __args)
+	{ __a.construct(__p, std::forward<_Args>(__args)...); }
+
+      /**
+       *  @brief  Destroy an object of type `_Up`
+       *  @param  __a  An allocator.
+       *  @param  __p  Pointer to the object to destroy
+       *
+       *  Calls `p->_Up()`.
+      */
+      template<typename _Up>
+	static _GLIBCXX20_CONSTEXPR void
+	destroy(allocator_type&, _Up* __p)
+	noexcept(is_nothrow_destructible<_Up>::value)
+	{ __p->~_Up(); }
+
+      /**
+       *  @brief  The maximum supported allocation size
+       *  @return `numeric_limits<size_t>::max() / sizeof(value_type)`
+      */
+      static _GLIBCXX20_CONSTEXPR size_type
+      max_size(const allocator_type&) noexcept
+      { return size_t(-1) / sizeof(value_type); }
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // C++17
+#endif // _GLIBCXX_MEMORY_RESOURCE_H
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index dc5c2034b8f..abdc2e04cdd 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -71,12 +71,12 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Tp>
       using deque = std::deque<_Tp, polymorphic_allocator<_Tp>>;
   } // namespace pmr
diff --git a/libstdc++-v3/include/std/forward_list b/libstdc++-v3/include/std/forward_list
index 21d617b00e9..fe99e5ed5ef 100644
--- a/libstdc++-v3/include/std/forward_list
+++ b/libstdc++-v3/include/std/forward_list
@@ -44,12 +44,12 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Tp>
       using forward_list = std::forward_list<_Tp, polymorphic_allocator<_Tp>>;
   } // namespace pmr
diff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list
index d7ef94317b1..9151e98cb88 100644
--- a/libstdc++-v3/include/std/list
+++ b/libstdc++-v3/include/std/list
@@ -68,12 +68,12 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Tp>
       using list = std::list<_Tp, polymorphic_allocator<_Tp>>;
   } // namespace pmr
diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map
index 93c956af916..ce07f29ee09 100644
--- a/libstdc++-v3/include/std/map
+++ b/libstdc++-v3/include/std/map
@@ -68,12 +68,12 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Key, typename _Tp, typename _Cmp = std::less<_Key>>
       using map
 	= std::map<_Key, _Tp, _Cmp,
diff --git a/libstdc++-v3/include/std/memory_resource b/libstdc++-v3/include/std/memory_resource
index 745422ad5eb..19c922516d5 100644
--- a/libstdc++-v3/include/std/memory_resource
+++ b/libstdc++-v3/include/std/memory_resource
@@ -33,22 +33,12 @@
 
 #if __cplusplus >= 201703L
 
-#include <new>
+#include <bits/memory_resource.h>
 #include <vector>			// vector
-#include <cstddef>			// size_t, max_align_t, byte
 #include <shared_mutex>			// shared_mutex
 #include <bits/align.h>			// align
-#include <bits/functexcept.h>		// __throw_bad_array_new_length
-#include <bits/uses_allocator.h>	// allocator_arg_t, __use_alloc
-#include <bits/uses_allocator_args.h>	// uninitialized_construct_using_alloc
-#include <ext/numeric_traits.h>
 #include <debug/assertions.h>
 
-#if ! __cpp_lib_make_obj_using_allocator
-# include <bits/utility.h>		// index_sequence
-# include <tuple>			// tuple, forward_as_tuple
-#endif
-
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -62,12 +52,7 @@ namespace pmr
 # define __cpp_lib_memory_resource 1
 #endif
 
-  class memory_resource;
-
-#if __cplusplus == 201703L
-  template<typename _Tp>
-    class polymorphic_allocator;
-#else // C++20
+#if __cplusplus >= 202002L
 # define __cpp_lib_polymorphic_allocator 201902L
   template<typename _Tp = std::byte>
     class polymorphic_allocator;
@@ -103,451 +88,6 @@ namespace pmr
   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(); // key function
-
-    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 ::operator new(__bytes, 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); }
-
-    [[nodiscard]]
-    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;
-  };
-
-  [[nodiscard]]
-  inline bool
-  operator==(const memory_resource& __a, const memory_resource& __b) noexcept
-  { return &__a == &__b || __a.is_equal(__b); }
-
-#if __cpp_impl_three_way_comparison < 201907L
-  [[nodiscard]]
-  inline bool
-  operator!=(const memory_resource& __a, const memory_resource& __b) noexcept
-  { return !(__a == __b); }
-#endif
-
-  // 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 ((__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Tp)) < __n)
-	  std::__throw_bad_array_new_length();
-	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)); }
-
-#if __cplusplus > 201703L
-      [[nodiscard]] void*
-      allocate_bytes(size_t __nbytes,
-		     size_t __alignment = alignof(max_align_t))
-      { return _M_resource->allocate(__nbytes, __alignment); }
-
-      void
-      deallocate_bytes(void* __p, size_t __nbytes,
-		       size_t __alignment = alignof(max_align_t))
-      { _M_resource->deallocate(__p, __nbytes, __alignment); }
-
-      template<typename _Up>
-	[[nodiscard]] _Up*
-	allocate_object(size_t __n = 1)
-	{
-	  if ((__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Up)) < __n)
-	    std::__throw_bad_array_new_length();
-	  return static_cast<_Up*>(allocate_bytes(__n * sizeof(_Up),
-						  alignof(_Up)));
-	}
-
-      template<typename _Up>
-	void
-	deallocate_object(_Up* __p, size_t __n = 1)
-	{ deallocate_bytes(__p, __n * sizeof(_Up), alignof(_Up)); }
-
-      template<typename _Up, typename... _CtorArgs>
-	[[nodiscard]] _Up*
-	new_object(_CtorArgs&&... __ctor_args)
-	{
-	  _Up* __p = allocate_object<_Up>();
-	  __try
-	    {
-	      construct(__p, std::forward<_CtorArgs>(__ctor_args)...);
-	    }
-	  __catch (...)
-	    {
-	      deallocate_object(__p);
-	      __throw_exception_again;
-	    }
-	  return __p;
-	}
-
-      template<typename _Up>
-	void
-	delete_object(_Up* __p)
-	{
-	  __p->~_Up();
-	  deallocate_object(__p);
-	}
-#endif // C++2a
-
-#if ! __cpp_lib_make_obj_using_allocator
-      template<typename _Tp1, typename... _Args>
-	__attribute__((__nonnull__))
-	typename __not_pair<_Tp1>::type
-	construct(_Tp1* __p, _Args&&... __args)
-	{
-	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-	  // 2969. polymorphic_allocator::construct() shouldn't pass resource()
-	  using __use_tag
-	    = std::__uses_alloc_t<_Tp1, polymorphic_allocator, _Args...>;
-	  if constexpr (is_base_of_v<__uses_alloc0, __use_tag>)
-	    ::new(__p) _Tp1(std::forward<_Args>(__args)...);
-	  else if constexpr (is_base_of_v<__uses_alloc1_, __use_tag>)
-	    ::new(__p) _Tp1(allocator_arg, *this,
-			    std::forward<_Args>(__args)...);
-	  else
-	    ::new(__p) _Tp1(std::forward<_Args>(__args)..., *this);
-	}
-
-      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_i, __x),
-				      _S_construct_p(__y_tag, __y_i, __y));
-	}
-
-      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,
-	      std::forward_as_tuple(std::forward<_Up>(__x)),
-	      std::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,
-	      std::forward_as_tuple(__pr.first),
-	      std::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,
-	      std::forward_as_tuple(std::forward<_Up>(__pr.first)),
-	      std::forward_as_tuple(std::forward<_Vp>(__pr.second)));
-	}
-#else // make_obj_using_allocator
-      template<typename _Tp1, typename... _Args>
-	__attribute__((__nonnull__))
-	void
-	construct(_Tp1* __p, _Args&&... __args)
-	{
-	  std::uninitialized_construct_using_allocator(__p, *this,
-	      std::forward<_Args>(__args)...);
-	}
-#endif
-
-      template<typename _Up>
-	_GLIBCXX20_DEPRECATED_SUGGEST("allocator_traits::destroy")
-	__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; }
-
-      // _GLIBCXX_RESOLVE_LIB_DEFECTS
-      // 3683. operator== for polymorphic_allocator cannot deduce template arg
-      [[nodiscard]]
-      friend bool
-      operator==(const polymorphic_allocator& __a,
-		 const polymorphic_allocator& __b) noexcept
-      { return *__a.resource() == *__b.resource(); }
-
-#if __cpp_impl_three_way_comparison < 201907L
-      [[nodiscard]]
-      friend bool
-      operator!=(const polymorphic_allocator& __a,
-		 const polymorphic_allocator& __b) noexcept
-      { return !(__a == __b); }
-#endif
-
-    private:
-#if ! __cpp_lib_make_obj_using_allocator
-      using __uses_alloc1_ = __uses_alloc1<polymorphic_allocator>;
-      using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>;
-
-      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 }; }
-#endif
-
-      memory_resource* _M_resource;
-    };
-
-  template<typename _Tp1, typename _Tp2>
-    [[nodiscard]]
-    inline bool
-    operator==(const polymorphic_allocator<_Tp1>& __a,
-	       const polymorphic_allocator<_Tp2>& __b) noexcept
-    { return *__a.resource() == *__b.resource(); }
-
-#if __cpp_impl_three_way_comparison < 201907L
-  template<typename _Tp1, typename _Tp2>
-    [[nodiscard]]
-    inline bool
-    operator!=(const polymorphic_allocator<_Tp1>& __a,
-	       const polymorphic_allocator<_Tp2>& __b) noexcept
-    { return !(__a == __b); }
-#endif
-
-} // namespace pmr
-
-  /// Partial specialization for std::pmr::polymorphic_allocator
-  template<typename _Tp>
-    struct allocator_traits<pmr::polymorphic_allocator<_Tp>>
-    {
-      /// The allocator type
-      using allocator_type = pmr::polymorphic_allocator<_Tp>;
-
-      /// The allocated type
-      using value_type = _Tp;
-
-      /// The allocator's pointer type.
-      using pointer = _Tp*;
-
-      /// The allocator's const pointer type.
-      using const_pointer = const _Tp*;
-
-      /// The allocator's void pointer type.
-      using void_pointer = void*;
-
-      /// The allocator's const void pointer type.
-      using const_void_pointer = const void*;
-
-      /// The allocator's difference type
-      using difference_type = std::ptrdiff_t;
-
-      /// The allocator's size type
-      using size_type = std::size_t;
-
-      /** @{
-       * A `polymorphic_allocator` does not propagate when a
-       * container is copied, moved, or swapped.
-       */
-      using propagate_on_container_copy_assignment = false_type;
-      using propagate_on_container_move_assignment = false_type;
-      using propagate_on_container_swap = false_type;
-
-      static allocator_type
-      select_on_container_copy_construction(const allocator_type&) noexcept
-      { return allocator_type(); }
-      /// @}
-
-      /// Whether all instances of the allocator type compare equal.
-      using is_always_equal = false_type;
-
-      template<typename _Up>
-	using rebind_alloc = pmr::polymorphic_allocator<_Up>;
-
-      template<typename _Up>
-	using rebind_traits = allocator_traits<pmr::polymorphic_allocator<_Up>>;
-
-      /**
-       *  @brief  Allocate memory.
-       *  @param  __a  An allocator.
-       *  @param  __n  The number of objects to allocate space for.
-       *
-       *  Calls `a.allocate(n)`.
-      */
-      [[nodiscard]] static pointer
-      allocate(allocator_type& __a, size_type __n)
-      { return __a.allocate(__n); }
-
-      /**
-       *  @brief  Allocate memory.
-       *  @param  __a  An allocator.
-       *  @param  __n  The number of objects to allocate space for.
-       *  @return Memory of suitable size and alignment for `n` objects
-       *          of type `value_type`.
-       *
-       *  The third parameter is ignored..
-       *
-       *  Returns `a.allocate(n)`.
-      */
-      [[nodiscard]] static pointer
-      allocate(allocator_type& __a, size_type __n, const_void_pointer)
-      { return __a.allocate(__n); }
-
-      /**
-       *  @brief  Deallocate memory.
-       *  @param  __a  An allocator.
-       *  @param  __p  Pointer to the memory to deallocate.
-       *  @param  __n  The number of objects space was allocated for.
-       *
-       *  Calls `a.deallocate(p, n)`.
-      */
-      static void
-      deallocate(allocator_type& __a, pointer __p, size_type __n)
-      { __a.deallocate(__p, __n); }
-
-      /**
-       *  @brief  Construct an object of type `_Up`
-       *  @param  __a  An allocator.
-       *  @param  __p  Pointer to memory of suitable size and alignment for
-       *	       an object of type `_Up`.
-       *  @param  __args Constructor arguments.
-       *
-       *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
-       *  in C++11, C++14 and C++17. Changed in C++20 to call
-       *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
-      */
-      template<typename _Up, typename... _Args>
-	static void
-	construct(allocator_type& __a, _Up* __p, _Args&&... __args)
-	{ __a.construct(__p, std::forward<_Args>(__args)...); }
-
-      /**
-       *  @brief  Destroy an object of type `_Up`
-       *  @param  __a  An allocator.
-       *  @param  __p  Pointer to the object to destroy
-       *
-       *  Calls `p->_Up()`.
-      */
-      template<typename _Up>
-	static _GLIBCXX20_CONSTEXPR void
-	destroy(allocator_type&, _Up* __p)
-	noexcept(is_nothrow_destructible<_Up>::value)
-	{ __p->~_Up(); }
-
-      /**
-       *  @brief  The maximum supported allocation size
-       *  @return `numeric_limits<size_t>::max() / sizeof(value_type)`
-      */
-      static _GLIBCXX20_CONSTEXPR size_type
-      max_size(const allocator_type&) noexcept
-      { return size_t(-1) / sizeof(value_type); }
-    };
-
-namespace pmr
-{
   /// Parameters for tuning a pool resource's behaviour.
   struct pool_options
   {
diff --git a/libstdc++-v3/include/std/regex b/libstdc++-v3/include/std/regex
index d1b6a6c68c3..491bced23b5 100644
--- a/libstdc++-v3/include/std/regex
+++ b/libstdc++-v3/include/std/regex
@@ -67,12 +67,12 @@
 #include <bits/regex_executor.h>
 
 #if __cplusplus >= 201703L && _GLIBCXX_USE_CXX11_ABI
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _BidirectionalIterator>
       using match_results
 	= std::match_results<_BidirectionalIterator, polymorphic_allocator<
diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set
index 45fed14c51e..551c77727f1 100644
--- a/libstdc++-v3/include/std/set
+++ b/libstdc++-v3/include/std/set
@@ -68,12 +68,12 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Key, typename _Cmp = std::less<_Key>>
       using set = std::set<_Key, _Cmp, polymorphic_allocator<_Key>>;
     template<typename _Key, typename _Cmp = std::less<_Key>>
diff --git a/libstdc++-v3/include/std/stacktrace b/libstdc++-v3/include/std/stacktrace
index 8e6c79a2f4f..1efaf253abb 100644
--- a/libstdc++-v3/include/std/stacktrace
+++ b/libstdc++-v3/include/std/stacktrace
@@ -33,6 +33,7 @@
 #include <new>
 #include <string>
 #include <sstream>
+#include <bits/memory_resource.h>
 #include <bits/stl_algobase.h>
 #include <bits/stl_algo.h>
 #include <bits/stl_iterator.h>
@@ -758,7 +759,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     using stacktrace
       = basic_stacktrace<polymorphic_allocator<stacktrace_entry>>;
   }
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index b1d8b6a34dd..24051663f74 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -54,11 +54,11 @@
 #include <bits/basic_string.tcc>
 
 #if __cplusplus >= 201703L && _GLIBCXX_USE_CXX11_ABI
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _CharT, typename _Traits = char_traits<_CharT>>
       using basic_string = std::basic_string<_CharT, _Traits,
 					     polymorphic_allocator<_CharT>>;
diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map
index bb14ffa7f2e..e13bb9a2148 100644
--- a/libstdc++-v3/include/std/unordered_map
+++ b/libstdc++-v3/include/std/unordered_map
@@ -53,12 +53,12 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Key, typename _Tp, typename _Hash = std::hash<_Key>,
 	     typename _Pred = std::equal_to<_Key>>
       using unordered_map
diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set
index 777e3b81116..8b665718a83 100644
--- a/libstdc++-v3/include/std/unordered_set
+++ b/libstdc++-v3/include/std/unordered_set
@@ -53,12 +53,12 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr
   {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Key, typename _Hash = std::hash<_Key>,
 	     typename _Pred = std::equal_to<_Key>>
       using unordered_set
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index a880dfcac6f..d7f69fd7a48 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -75,11 +75,11 @@
 #endif
 
 #if __cplusplus >= 201703L
+#include <bits/memory_resource.h>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace pmr {
-    template<typename _Tp> class polymorphic_allocator;
     template<typename _Tp>
       using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>;
   } // namespace pmr
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/types/pmr_typedefs.cc b/libstdc++-v3/testsuite/21_strings/basic_string/types/pmr_typedefs.cc
index 51bbfb0aba0..cabe59090af 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/types/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/types/pmr_typedefs.cc
@@ -19,7 +19,8 @@
 // { dg-require-effective-target cxx11_abi }
 
 #include <string>
-#include <memory_resource>
+
+std::pmr::string s = "polly";
 
 struct T : std::char_traits<char> { };
 
diff --git a/libstdc++-v3/testsuite/23_containers/deque/types/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/deque/types/pmr_typedefs.cc
index f6493e8131e..c973d4f432c 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/types/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/types/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <deque>
-#include <memory_resource>
+
+std::pmr::deque<int> c{1, 2, 3, 4};
 
 struct X { };
 
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/forward_list/pmr_typedefs.cc
index 8559783881f..f66e53f62a8 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <forward_list>
-#include <memory_resource>
+
+std::pmr::forward_list<int> c{1, 2, 3, 4};
 
 struct X { };
 
diff --git a/libstdc++-v3/testsuite/23_containers/list/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/list/pmr_typedefs.cc
index d6c408aa88f..3c5ef794720 100644
--- a/libstdc++-v3/testsuite/23_containers/list/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <list>
-#include <memory_resource>
+
+std::pmr::list<int> c{1, 2, 3, 4};
 
 struct X { };
 
diff --git a/libstdc++-v3/testsuite/23_containers/map/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/map/pmr_typedefs.cc
index cc82fcf5fc9..91602ccbc17 100644
--- a/libstdc++-v3/testsuite/23_containers/map/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <map>
-#include <memory_resource>
+
+std::pmr::map<int, int> c{{1,0}, {2,0}, {3,0}, {4,0}};
 
 struct X { };
 struct Y { };
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/multimap/pmr_typedefs.cc
index 2312ad680a2..13b0970a100 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <map>
-#include <memory_resource>
+
+std::pmr::multimap<int, int> c{{1,0}, {2,0}, {3,0}, {4,0}};
 
 struct X { };
 struct Y { };
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/multiset/pmr_typedefs.cc
index 19e28023533..f1013b6efdc 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <set>
-#include <memory_resource>
+
+std::pmr::multiset<int> c{1, 2, 3, 4};
 
 struct X { };
 struct Cmp { bool operator()(X, X) const { return false; } };
diff --git a/libstdc++-v3/testsuite/23_containers/set/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/set/pmr_typedefs.cc
index a65d0719e52..4b70b984729 100644
--- a/libstdc++-v3/testsuite/23_containers/set/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <set>
-#include <memory_resource>
+
+std::pmr::set<int> c{1, 2, 3, 4};
 
 struct X { };
 struct Cmp { bool operator()(X, X) const { return false; } };
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/pmr_typedefs.cc
index 7c00633bf1c..d8e17139f05 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <unordered_map>
-#include <memory_resource>
+
+std::pmr::unordered_map<int, int> c{{1,0}, {2,0}, {3,0}, {4,0}};
 
 struct X { };
 struct Y { };
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/pmr_typedefs.cc
index 51d598e7e25..6dfe1d5b8bd 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <unordered_map>
-#include <memory_resource>
+
+std::pmr::unordered_multimap<int, int> c{{1,0}, {2,0}, {3,0}, {4,0}};
 
 struct X { };
 struct Y { };
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/pmr_typedefs.cc
index f5b9d6c0282..4deeb710686 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <unordered_set>
-#include <memory_resource>
+
+std::pmr::unordered_multiset<int> c{1, 2, 3, 4};
 
 struct X { };
 struct Hash { std::size_t operator()(X) const { return 0; } };
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/pmr_typedefs.cc
index 5fe33e880f9..4736cfff86f 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <unordered_set>
-#include <memory_resource>
+
+std::pmr::unordered_set<int> c{1, 2, 3, 4};
 
 struct X { };
 struct Hash { std::size_t operator()(X) const { return 0; } };
diff --git a/libstdc++-v3/testsuite/23_containers/vector/pmr_typedefs.cc b/libstdc++-v3/testsuite/23_containers/vector/pmr_typedefs.cc
index 0fbc32bb185..f4969e3364e 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/pmr_typedefs.cc
@@ -18,7 +18,8 @@
 // { dg-do compile { target c++17 } }
 
 #include <vector>
-#include <memory_resource>
+
+std::pmr::vector<int> c{1, 2, 3, 4};
 
 struct X { };
 
diff --git a/libstdc++-v3/testsuite/28_regex/match_results/pmr_typedefs.cc b/libstdc++-v3/testsuite/28_regex/match_results/pmr_typedefs.cc
index b8c22d03a17..5ff4c771a6c 100644
--- a/libstdc++-v3/testsuite/28_regex/match_results/pmr_typedefs.cc
+++ b/libstdc++-v3/testsuite/28_regex/match_results/pmr_typedefs.cc
@@ -20,7 +20,8 @@
 // { dg-require-effective-target cxx11_abi }
 
 #include <regex>
-#include <memory_resource>
+
+std::pmr::match_results<const char*> m;
 
 struct X;
 static_assert(std::is_same_v<std::pmr::match_results<X*>,
-- 
2.34.3


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-19 22:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-19 22:42 [committed] libstdc++: Ensure pmr aliases work without <memory_resource> Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).