Index: docs/FeatureTestMacroTable.rst
===================================================================
--- docs/FeatureTestMacroTable.rst
+++ docs/FeatureTestMacroTable.rst
@@ -126,7 +126,7 @@
     ------------------------------------------------- -----------------
     ``__cpp_lib_math_special_functions``              *unimplemented*  
     ------------------------------------------------- -----------------
-    ``__cpp_lib_memory_resource``                     *unimplemented*  
+    ``__cpp_lib_memory_resource``                     ``201603L``      
     ------------------------------------------------- -----------------
     ``__cpp_lib_node_extract``                        ``201606L``      
     ------------------------------------------------- -----------------
Index: include/CMakeLists.txt
===================================================================
--- include/CMakeLists.txt
+++ include/CMakeLists.txt
@@ -10,6 +10,7 @@
   __hash_table
   __libcpp_version
   __locale
+  __memory_resource_base
   __mutex_base
   __node_handle
   __nullptr
@@ -111,6 +112,7 @@
   map
   math.h
   memory
+  memory_resource
   module.modulemap
   mutex
   new
Index: include/__memory_resource_base
===================================================================
--- /dev/null
+++ include/__memory_resource_base
@@ -0,0 +1,315 @@
+// -*- C++ -*-
+//===------------------------ memory_resource -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MEMORY_RESOURCE_BASE
+#define _LIBCPP___MEMORY_RESOURCE_BASE
+
+#ifndef _LIBCPP_CXX03_LANG
+
+/**
+    memory_resource synopsis
+
+// C++17
+
+namespace std {
+namespace pmr {
+
+  class memory_resource;
+
+  bool operator==(const memory_resource& a,
+                  const memory_resource& b) noexcept;
+  bool operator!=(const memory_resource& a,
+                  const memory_resource& b) noexcept;
+
+  template <class Tp> class polymorphic_allocator;
+
+  template <class T1, class T2>
+  bool operator==(const polymorphic_allocator<T1>& a,
+                  const polymorphic_allocator<T2>& b) noexcept;
+  template <class T1, class T2>
+  bool operator!=(const polymorphic_allocator<T1>& a,
+                  const polymorphic_allocator<T2>& b) noexcept;
+
+  // Global memory resources
+  memory_resource* set_default_resource(memory_resource* r) noexcept;
+  memory_resource* get_default_resource() noexcept;
+
+} // namespace pmr
+} // namespace std
+
+ */
+
+#include <__config>
+#include <__functional_base>
+#include <limits>
+#include <memory>
+#include <new>
+#include <stdexcept>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <cstddef>
+#include <cstdlib>
+#include <__debug>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace pmr
+{
+
+// 23.12.2, mem.res.class
+class _LIBCPP_TYPE_VIS memory_resource
+{
+    static const size_t __max_align = alignof(max_align_t);
+
+// 23.12.2.1, mem.res.public
+public:
+    virtual ~memory_resource() = default;
+
+    _LIBCPP_INLINE_VISIBILITY
+    void* allocate(size_t __bytes, size_t __align = __max_align)
+        { return do_allocate(__bytes, __align); }
+
+    _LIBCPP_INLINE_VISIBILITY
+    void deallocate(void * __p, size_t __bytes, size_t __align = __max_align)
+        { do_deallocate(__p, __bytes, __align); }
+
+    _LIBCPP_INLINE_VISIBILITY
+    bool is_equal(memory_resource const & __other) const _NOEXCEPT
+        { return do_is_equal(__other); }
+
+// 23.12.2.2, mem.res.private
+private:
+    virtual void* do_allocate(size_t, size_t) = 0;
+    virtual void do_deallocate(void*, size_t, size_t) = 0;
+    virtual bool do_is_equal(memory_resource const &) const _NOEXCEPT = 0;
+};
+
+// 23.12.2.3, mem.res.eq
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator==(memory_resource const & __lhs,
+                memory_resource const & __rhs) _NOEXCEPT
+{
+    return &__lhs == &__rhs || __lhs.is_equal(__rhs);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator!=(memory_resource const & __lhs,
+                memory_resource const & __rhs) _NOEXCEPT
+{
+    return !(__lhs == __rhs);
+}
+
+// 23.12.4, mem.res.global
+
+_LIBCPP_FUNC_VIS
+memory_resource * get_default_resource() _NOEXCEPT;
+
+_LIBCPP_FUNC_VIS
+memory_resource * set_default_resource(memory_resource *) _NOEXCEPT;
+
+// 23.12.3, mem.poly.allocator.class
+template <class _ValueType>
+class _LIBCPP_TEMPLATE_VIS polymorphic_allocator
+{
+public:
+    typedef _ValueType value_type;
+
+    // 23.12.3.1, mem.poly.allocator.ctor
+    _LIBCPP_INLINE_VISIBILITY
+    polymorphic_allocator() _NOEXCEPT
+      : __res_(_VSTD::pmr::get_default_resource())
+    {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    polymorphic_allocator(memory_resource * __r) _NOEXCEPT
+      : __res_(__r)
+    {}
+
+    polymorphic_allocator(polymorphic_allocator const &) = default;
+
+    template <class _Tp>
+    _LIBCPP_INLINE_VISIBILITY
+    polymorphic_allocator(polymorphic_allocator<_Tp> const & __other) _NOEXCEPT
+      : __res_(__other.resource())
+    {}
+
+    polymorphic_allocator &
+    operator=(polymorphic_allocator const &) = delete;
+
+    // 23.12.3.2, mem.poly.allocator.mem
+    _LIBCPP_INLINE_VISIBILITY
+    _ValueType* allocate(size_t __n) {
+        if (__n > __max_size()) {
+            __throw_length_error(
+                "std::pmr::polymorphic_allocator<T>::allocate(size_t n)"
+                " 'n' exceeds maximum supported size");
+        }
+        return static_cast<_ValueType*>(
+            __res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType))
+        );
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    void deallocate(_ValueType * __p, size_t __n) {
+        _LIBCPP_ASSERT(__n <= __max_size(),
+                       "deallocate called for size which exceeds max_size()");
+        __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType));
+    }
+
+    template <class _Tp, class ..._Ts>
+    _LIBCPP_INLINE_VISIBILITY
+    void construct(_Tp* __p, _Ts &&... __args)
+    {
+        _VSTD::__user_alloc_construct_impl(
+            typename __uses_alloc_ctor<_Tp, polymorphic_allocator&, _Ts...>::type(),
+            __p, *this, _VSTD::forward<_Ts>(__args)...
+        );
+    }
+
+    template <class _T1, class _T2, class ..._Args1, class ..._Args2>
+    _LIBCPP_INLINE_VISIBILITY
+    void construct(pair<_T1, _T2>* __p, piecewise_construct_t,
+                   tuple<_Args1...> __x, tuple<_Args2...> __y)
+    {
+        ::new ((void*)__p) pair<_T1, _T2>(piecewise_construct
+          , __transform_tuple(
+              typename __uses_alloc_ctor<
+                  _T1, polymorphic_allocator&, _Args1...
+              >::type()
+            , _VSTD::move(__x)
+            , typename __make_tuple_indices<sizeof...(_Args1)>::type{}
+          )
+          , __transform_tuple(
+              typename __uses_alloc_ctor<
+                  _T2, polymorphic_allocator&, _Args2...
+              >::type()
+            , _VSTD::move(__y)
+            , typename __make_tuple_indices<sizeof...(_Args2)>::type{}
+          )
+        );
+    }
+
+    template <class _T1, class _T2>
+    _LIBCPP_INLINE_VISIBILITY
+    void construct(pair<_T1, _T2>* __p) {
+        construct(__p, piecewise_construct, tuple<>(), tuple<>());
+    }
+
+    template <class _T1, class _T2, class _Up, class _Vp>
+    _LIBCPP_INLINE_VISIBILITY
+    void construct(pair<_T1, _T2> * __p, _Up && __u, _Vp && __v) {
+        construct(__p, piecewise_construct
+          , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__u))
+          , _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__v)));
+    }
+
+    template <class _T1, class _T2, class _U1, class _U2>
+    _LIBCPP_INLINE_VISIBILITY
+    void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> const & __pr) {
+        construct(__p, piecewise_construct
+            , _VSTD::forward_as_tuple(__pr.first)
+            , _VSTD::forward_as_tuple(__pr.second));
+    }
+
+    template <class _T1, class _T2, class _U1, class _U2>
+    _LIBCPP_INLINE_VISIBILITY
+    void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> && __pr){
+        construct(__p, piecewise_construct
+            , _VSTD::forward_as_tuple(_VSTD::forward<_U1>(__pr.first))
+            , _VSTD::forward_as_tuple(_VSTD::forward<_U2>(__pr.second)));
+    }
+
+    template <class _Tp>
+    _LIBCPP_INLINE_VISIBILITY
+    void destroy(_Tp * __p)
+        { __p->~_Tp(); }
+
+    _LIBCPP_INLINE_VISIBILITY
+    polymorphic_allocator
+    select_on_container_copy_construction() const _NOEXCEPT
+        { return polymorphic_allocator(); }
+
+    _LIBCPP_INLINE_VISIBILITY
+    memory_resource * resource() const _NOEXCEPT
+        { return __res_; }
+
+private:
+    template <class ..._Args, size_t ..._Idx>
+    _LIBCPP_INLINE_VISIBILITY
+    tuple<_Args&&...>
+    __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t,
+                      __tuple_indices<_Idx...>)
+    {
+        return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...);
+    }
+
+    template <class ..._Args, size_t ..._Idx>
+    _LIBCPP_INLINE_VISIBILITY
+    tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>
+    __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t,
+                      __tuple_indices<_Idx...>)
+    {
+        using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>;
+        return _Tup(allocator_arg, *this,
+                    _VSTD::get<_Idx>(_VSTD::move(__t))...);
+    }
+
+    template <class ..._Args, size_t ..._Idx>
+    _LIBCPP_INLINE_VISIBILITY
+    tuple<_Args&&..., polymorphic_allocator&>
+    __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t,
+                      __tuple_indices<_Idx...>)
+    {
+        using _Tup = tuple<_Args&&..., polymorphic_allocator&>;
+        return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., *this);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    size_t __max_size() const _NOEXCEPT
+        { return numeric_limits<size_t>::max() / sizeof(value_type); }
+
+    memory_resource * __res_;
+};
+
+// 23.12.3.3, mem.poly.allocator.eq
+
+template <class _Tp, class _Up>
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator==(polymorphic_allocator<_Tp> const & __lhs,
+                polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
+{
+    return *__lhs.resource() == *__rhs.resource();
+}
+
+template <class _Tp, class _Up>
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator!=(polymorphic_allocator<_Tp> const & __lhs,
+                polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
+{
+    return !(__lhs == __rhs);
+}
+
+} // namespace pmr
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif /* _LIBCPP_CXX03_LANG */
+
+#endif /* _LIBCPP___MEMORY_RESOURCE_BASE */
Index: include/deque
===================================================================
--- include/deque
+++ include/deque
@@ -167,6 +167,10 @@
 #include <stdexcept>
 #include <version>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -3034,6 +3038,16 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _ValueT>
+    using deque = _VSTD::deque<_ValueT, polymorphic_allocator<_ValueT>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 _LIBCPP_POP_MACROS
 
 #endif  // _LIBCPP_DEQUE
Index: include/forward_list
===================================================================
--- include/forward_list
+++ include/forward_list
@@ -185,6 +185,10 @@
 #include <algorithm>
 #include <version>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -1776,6 +1780,16 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _ValueT>
+    using forward_list = _VSTD::forward_list<_ValueT, polymorphic_allocator<_ValueT>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 _LIBCPP_POP_MACROS
 
 #endif  // _LIBCPP_FORWARD_LIST
Index: include/list
===================================================================
--- include/list
+++ include/list
@@ -190,6 +190,10 @@
 
 #include <__debug>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -2483,6 +2487,16 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _ValueT>
+    using list = _VSTD::list<_ValueT, polymorphic_allocator<_ValueT>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 _LIBCPP_POP_MACROS
 
 #endif  // _LIBCPP_LIST
Index: include/map
===================================================================
--- include/map
+++ include/map
@@ -486,6 +486,10 @@
 #include <type_traits>
 #include <version>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -2243,4 +2247,17 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _KeyT, class _ValueT, class _CompareT = _VSTD::less<_KeyT>>
+    using map = _VSTD::map<_KeyT, _ValueT, _CompareT, polymorphic_allocator<_VSTD::pair<const _KeyT, _ValueT>>>;
+
+    template <class _KeyT, class _ValueT, class _CompareT = _VSTD::less<_KeyT>>
+    using multimap = _VSTD::multimap<_KeyT, _ValueT, _CompareT, polymorphic_allocator<_VSTD::pair<const _KeyT, _ValueT>>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 #endif  // _LIBCPP_MAP
Index: include/memory_resource
===================================================================
--- /dev/null
+++ include/memory_resource
@@ -0,0 +1,359 @@
+// -*- C++ -*-
+//===------------------------ memory_resource -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_MEMORY_RESOURCE
+#define _LIBCPP_MEMORY_RESOURCE
+
+#ifndef _LIBCPP_CXX03_LANG
+
+/**
+    memory_resource synopsis
+
+// C++17
+
+namespace std {
+namespace pmr {
+
+  // Global memory resources
+  memory_resource* new_delete_resource() noexcept;
+  memory_resource* null_memory_resource() noexcept;
+
+  // Pool resource classes
+  struct pool_options;
+  class synchronized_pool_resource;
+  class unsynchronized_pool_resource;
+  class monotonic_buffer_resource;
+
+} // namespace pmr
+} // namespace std
+
+ */
+
+#include <__config>
+#include <__functional_base>
+#include <__memory_resource_base>
+#include <limits>
+#include <memory>
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#include <mutex>
+#endif
+#include <new>
+#include <stdexcept>
+#include <type_traits>
+#include <utility>
+#include <cstddef>
+#include <cstdlib>
+#include <__debug>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace pmr
+{
+
+// 23.12.4, mem.res.global
+
+_LIBCPP_FUNC_VIS
+memory_resource * new_delete_resource() _NOEXCEPT;
+
+_LIBCPP_FUNC_VIS
+memory_resource * null_memory_resource() _NOEXCEPT;
+
+// 23.12.5, mem.res.pool
+
+// 23.12.5.2, mem.res.pool.options
+
+struct _LIBCPP_TYPE_VIS pool_options {
+    size_t max_blocks_per_chunk = 0;
+    size_t largest_required_pool_block = 0;
+};
+
+// 23.12.5.1, mem.res.pool.overview
+
+
+class _LIBCPP_TYPE_VIS unsynchronized_pool_resource : public memory_resource
+{
+    class __fixed_pool;
+
+    class __adhoc_pool {
+        struct __chunk_header;
+        __chunk_header *__first_;
+
+    public:
+        _LIBCPP_INLINE_VISIBILITY
+        explicit __adhoc_pool() : __first_(nullptr) {}
+
+        void __release_ptr(memory_resource *__upstream);
+        void *__do_allocate(memory_resource *__upstream,
+                            size_t __bytes, size_t __align);
+        void __do_deallocate(memory_resource *__upstream,
+                             void *__p, size_t __bytes, size_t __align);
+    };
+
+    static const size_t __min_blocks_per_chunk = 16;
+    static const size_t __min_bytes_per_chunk = 1024;
+    static const size_t __max_blocks_per_chunk = (size_t(1) << 20);
+    static const size_t __max_bytes_per_chunk = (size_t(1) << 30);
+
+    static const int __log2_smallest_block_size = 3;
+    static const size_t __smallest_block_size = 8;
+    static const size_t __default_largest_block_size = (size_t(1) << 20);
+    static const size_t __max_largest_block_size = (size_t(1) << 30);
+
+    size_t __pool_block_size(int __i) const;
+    int __log2_pool_block_size(int __i) const;
+    int __pool_index(size_t __bytes, size_t __align) const;
+
+public:
+    unsynchronized_pool_resource(const pool_options& __opts,
+                                 memory_resource* __upstream);
+
+    _LIBCPP_INLINE_VISIBILITY
+    unsynchronized_pool_resource()
+        : unsynchronized_pool_resource(pool_options(), get_default_resource()) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    explicit unsynchronized_pool_resource(memory_resource* __upstream)
+        : unsynchronized_pool_resource(pool_options(), __upstream) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    explicit unsynchronized_pool_resource(const pool_options& __opts)
+        : unsynchronized_pool_resource(__opts, get_default_resource()) {}
+
+    unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete;
+
+    _LIBCPP_INLINE_VISIBILITY
+    ~unsynchronized_pool_resource() override
+        { release(); }
+
+    unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete;
+
+    void release();
+
+    _LIBCPP_INLINE_VISIBILITY
+    memory_resource* upstream_resource() const
+        { return __res_; }
+
+    pool_options options() const;
+
+protected:
+    void *do_allocate(size_t __bytes, size_t __align) override; // key function
+
+    void do_deallocate(void *__p, size_t __bytes, size_t __align) override;
+
+    _LIBCPP_INLINE_VISIBILITY
+    bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override
+        { return &__other == this; }
+
+private:
+    memory_resource *__res_;
+    __adhoc_pool __adhoc_pool_;
+    __fixed_pool *__fixed_pools_;
+    int __num_fixed_pools_;
+    uint32_t __options_max_blocks_per_chunk_;
+};
+
+class _LIBCPP_TYPE_VIS synchronized_pool_resource : public memory_resource
+{
+public:
+    _LIBCPP_INLINE_VISIBILITY
+    synchronized_pool_resource(const pool_options& __opts, memory_resource *__upstream)
+        : __unsync_(__opts, __upstream) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    synchronized_pool_resource()
+        : synchronized_pool_resource(pool_options(), get_default_resource()) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    explicit synchronized_pool_resource(memory_resource *__upstream)
+        : synchronized_pool_resource(pool_options(), __upstream) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    explicit synchronized_pool_resource(const pool_options& __opts)
+        : synchronized_pool_resource(__opts, get_default_resource()) {}
+
+    synchronized_pool_resource(const synchronized_pool_resource&) = delete;
+
+    ~synchronized_pool_resource() override = default;
+
+    synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete;
+
+    _LIBCPP_INLINE_VISIBILITY
+    void release() {
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+        unique_lock<mutex> __lk(__mut_);
+#endif
+        __unsync_.release();
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    memory_resource* upstream_resource() const
+        { return __unsync_.upstream_resource(); }
+
+    _LIBCPP_INLINE_VISIBILITY
+    pool_options options() const
+        { return __unsync_.options(); }
+
+protected:
+    _LIBCPP_INLINE_VISIBILITY
+    void* do_allocate(size_t __bytes, size_t __align) override {
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+        unique_lock<mutex> __lk(__mut_);
+#endif
+        return __unsync_.allocate(__bytes, __align);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    void do_deallocate(void *__p, size_t __bytes, size_t __align) override {
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+        unique_lock<mutex> __lk(__mut_);
+#endif
+        return __unsync_.deallocate(__p, __bytes, __align);
+    }
+
+    bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override; // key function
+
+private:
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+    mutex __mut_;
+#endif
+    unsynchronized_pool_resource __unsync_;
+};
+
+// 23.12.6, mem.res.monotonic.buffer
+
+class _LIBCPP_TYPE_VIS monotonic_buffer_resource : public memory_resource
+{
+    static const size_t __default_buffer_capacity = 1024;
+    static const size_t __default_buffer_alignment = 16;
+
+    struct __chunk_header {
+        __chunk_header *__next_;
+        char *__start_;
+        char *__cur_;
+        size_t __align_;
+        size_t __allocation_size() {
+            return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this);
+        }
+        void *__try_allocate_from_chunk(size_t, size_t);
+    };
+
+    struct __initial_header {
+        char *__start_;
+        char *__cur_;
+        union {
+            char *__end_;
+            size_t __size_;
+        };
+        void *__try_allocate_from_chunk(size_t, size_t);
+    };
+
+public:
+    _LIBCPP_INLINE_VISIBILITY
+    monotonic_buffer_resource()
+        : monotonic_buffer_resource(
+            nullptr, __default_buffer_capacity, get_default_resource()) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    explicit monotonic_buffer_resource(size_t __initial_size)
+        : monotonic_buffer_resource(
+            nullptr, __initial_size, get_default_resource()) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    monotonic_buffer_resource(void *__buffer, size_t __buffer_size)
+        : monotonic_buffer_resource(
+            __buffer, __buffer_size, get_default_resource()) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    explicit monotonic_buffer_resource(memory_resource *__upstream)
+        : monotonic_buffer_resource(
+            nullptr, __default_buffer_capacity, __upstream) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    monotonic_buffer_resource(size_t __initial_size,
+                              memory_resource *__upstream)
+        : monotonic_buffer_resource(
+            nullptr, __initial_size, __upstream) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    monotonic_buffer_resource(void *__buffer, size_t __buffer_size,
+                              memory_resource *__upstream)
+        : __res_(__upstream)
+    {
+        __initial_.__start_ = static_cast<char *>(__buffer);
+        if (__buffer != nullptr) {
+            __initial_.__cur_ = static_cast<char *>(__buffer);
+            __initial_.__end_ = static_cast<char *>(__buffer) + __buffer_size;
+        } else {
+            __initial_.__cur_ = nullptr;
+            __initial_.__size_ = __buffer_size;
+        }
+        __chunks_ = nullptr;
+    }
+
+    monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;
+
+    _LIBCPP_INLINE_VISIBILITY
+    ~monotonic_buffer_resource() override
+        { release(); }
+
+    monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete;
+
+    _LIBCPP_INLINE_VISIBILITY
+    void release()
+    {
+        __initial_.__cur_ = __initial_.__start_;
+        while (__chunks_ != nullptr) {
+            __chunk_header *__next = __chunks_->__next_;
+            __res_->deallocate(
+                __chunks_->__start_,
+                __chunks_->__allocation_size(),
+                __chunks_->__align_
+            );
+            __chunks_ = __next;
+        }
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    memory_resource* upstream_resource() const
+        { return __res_; }
+
+protected:
+    void *do_allocate(size_t __bytes, size_t __alignment) override; // key function
+
+    _LIBCPP_INLINE_VISIBILITY
+    void do_deallocate(void*, size_t, size_t) override
+        {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override
+        { return this == _VSTD::addressof(__other); }
+
+private:
+    __initial_header __initial_;
+    __chunk_header *__chunks_;
+    memory_resource* __res_;
+};
+
+} // namespace pmr
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif /* _LIBCPP_CXX03_LANG */
+
+#endif /* _LIBCPP_MEMORY_RESOURCE */
Index: include/module.modulemap
===================================================================
--- include/module.modulemap
+++ include/module.modulemap
@@ -356,6 +356,10 @@
     header "memory"
     export *
   }
+  module memory_resource {
+    header "memory_resource"
+    export *
+  }
   module mutex {
     header "mutex"
     export *
@@ -505,6 +509,7 @@
   module __functional_base { header "__functional_base" export * }
   module __hash_table { header "__hash_table" export * }
   module __locale { header "__locale" export * }
+  module __memory_resource_base { header "__memory_resource_base" export * }
   module __mutex_base { header "__mutex_base" export * }
   module __split_buffer { header "__split_buffer" export * }
   module __sso_allocator { header "__sso_allocator" export * }
Index: include/regex
===================================================================
--- include/regex
+++ include/regex
@@ -770,6 +770,10 @@
 #include <deque>
 #include <version>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -6657,6 +6661,21 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template<class _BidirT>
+    using match_results = _VSTD::match_results<_BidirT, polymorphic_allocator<_VSTD::sub_match<_BidirT>>>;
+
+    using cmatch  = match_results<const char*>;
+    using wcmatch = match_results<const wchar_t*>;
+    using smatch  = match_results<_VSTD::pmr::string::const_iterator>;
+    using wsmatch = match_results<_VSTD::pmr::wstring::const_iterator>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 _LIBCPP_POP_MACROS
 
 #endif  // _LIBCPP_REGEX
Index: include/set
===================================================================
--- include/set
+++ include/set
@@ -429,6 +429,10 @@
 #include <functional>
 #include <version>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -1490,4 +1494,17 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _KeyT, class _CompareT = _VSTD::less<_KeyT>>
+    using set = _VSTD::set<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>;
+
+    template <class _KeyT, class _CompareT = _VSTD::less<_KeyT>>
+    using multiset = _VSTD::multiset<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 #endif  // _LIBCPP_SET
Index: include/string
===================================================================
--- include/string
+++ include/string
@@ -521,6 +521,10 @@
 
 #include <__debug>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -4360,6 +4364,21 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template<class _CharT, class _TraitsT = _VSTD::char_traits<_CharT>>
+    using basic_string = _VSTD::basic_string<_CharT, _TraitsT, polymorphic_allocator<_CharT>>;
+
+    using string    = basic_string<char>;
+    using u16string = basic_string<char16_t>;
+    using u32string = basic_string<char32_t>;
+    using wstring   = basic_string<wchar_t>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 _LIBCPP_POP_MACROS
 
 #endif  // _LIBCPP_STRING
Index: include/unordered_map
===================================================================
--- include/unordered_map
+++ include/unordered_map
@@ -413,6 +413,10 @@
 #include <tuple>
 #include <version>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #include <__debug>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -2442,4 +2446,17 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _KeyT, class _ValueT, class _HashT = _VSTD::hash<_KeyT>, class _PredT = _VSTD::equal_to<_KeyT>>
+    using unordered_map = _VSTD::unordered_map<_KeyT, _ValueT, _HashT, _PredT, polymorphic_allocator<_VSTD::pair<const _KeyT, _ValueT>>>;
+
+    template <class _KeyT, class _ValueT, class _HashT = _VSTD::hash<_KeyT>, class _PredT = _VSTD::equal_to<_KeyT>>
+    using unordered_multimap = _VSTD::unordered_multimap<_KeyT, _ValueT, _HashT, _PredT, polymorphic_allocator<_VSTD::pair<const _KeyT, _ValueT>>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 #endif  // _LIBCPP_UNORDERED_MAP
Index: include/unordered_set
===================================================================
--- include/unordered_set
+++ include/unordered_set
@@ -368,6 +368,10 @@
 
 #include <__debug>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -1677,4 +1681,17 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _KeyT, class _HashT = _VSTD::hash<_KeyT>, class _PredT = _VSTD::equal_to<_KeyT>>
+    using unordered_set = _VSTD::unordered_set<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>;
+
+    template <class _KeyT, class _HashT = _VSTD::hash<_KeyT>, class _PredT = _VSTD::equal_to<_KeyT>>
+    using unordered_multiset = _VSTD::unordered_multiset<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 #endif  // _LIBCPP_UNORDERED_SET
Index: include/vector
===================================================================
--- include/vector
+++ include/vector
@@ -286,6 +286,10 @@
 
 #include <__debug>
 
+#if _LIBCPP_STD_VER > 14
+#include <__memory_resource_base>
+#endif
+
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
@@ -3397,6 +3401,16 @@
 
 _LIBCPP_END_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 14
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace pmr
+{
+    template <class _ValueT>
+    using vector = _VSTD::vector<_ValueT, polymorphic_allocator<_ValueT>>;
+}
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
 _LIBCPP_POP_MACROS
 
 #endif  // _LIBCPP_VECTOR
Index: include/version
===================================================================
--- include/version
+++ include/version
@@ -183,7 +183,7 @@
 # define __cpp_lib_make_from_tuple                      201606L
 # define __cpp_lib_map_try_emplace                      201411L
 // # define __cpp_lib_math_special_functions               201603L
-// # define __cpp_lib_memory_resource                      201603L
+# define __cpp_lib_memory_resource                      201603L
 # define __cpp_lib_node_extract                         201606L
 # define __cpp_lib_nonmember_container_access           201411L
 # define __cpp_lib_not_fn                               201603L
Index: src/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt
+++ src/CMakeLists.txt
@@ -22,6 +22,7 @@
   iostream.cpp
   locale.cpp
   memory.cpp
+  memory_resource.cpp
   mutex.cpp
   mutex_destructor.cpp
   new.cpp
Index: src/memory_resource.cpp
===================================================================
--- /dev/null
+++ src/memory_resource.cpp
@@ -0,0 +1,567 @@
+//===------------------------ memory_resource.cpp -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "memory_resource"
+#include "memory"
+
+#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
+#include "atomic"
+#endif
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#include "mutex"
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace pmr {
+
+// memory_resource
+
+//memory_resource::~memory_resource() {}
+
+// new_delete_resource()
+
+#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
+static bool is_aligned_to(void *ptr, size_t align)
+{
+    void *p2 = ptr;
+    size_t space = 1;
+    void *result = _VSTD::align(align, 1, p2, space);
+    return (result == ptr);
+}
+#endif
+
+class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp
+    : public memory_resource
+{
+    void *do_allocate(size_t bytes, size_t align) override
+    {
+#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
+        return _VSTD::__libcpp_allocate(bytes, align);
+#else
+        if (bytes == 0)
+            bytes = 1;
+        void *result = _VSTD::__libcpp_allocate(bytes, align);
+        if (!is_aligned_to(result, align)) {
+            _VSTD::__libcpp_deallocate(result, bytes, align);
+            __throw_bad_alloc();
+        }
+        return result;
+#endif
+    }
+
+    void do_deallocate(void *p, size_t bytes, size_t align) override
+        { _VSTD::__libcpp_deallocate(p, bytes, align); }
+
+    bool do_is_equal(const memory_resource& other) const _NOEXCEPT override
+        { return &other == this; }
+};
+
+// null_memory_resource()
+
+class _LIBCPP_TYPE_VIS __null_memory_resource_imp
+    : public memory_resource
+{
+    void *do_allocate(size_t, size_t) override { __throw_bad_alloc(); }
+    void do_deallocate(void *, size_t, size_t) override {}
+    bool do_is_equal(const memory_resource& other) const _NOEXCEPT override
+        { return &other == this; }
+};
+
+namespace {
+
+union ResourceInitHelper {
+  struct {
+    __new_delete_memory_resource_imp new_delete_res;
+    __null_memory_resource_imp       null_res;
+  } resources;
+  char dummy;
+  _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {}
+  ~ResourceInitHelper() {}
+};
+// When compiled in C++14 this initialization should be a constant expression.
+// Only in C++11 is "init_priority" needed to ensure initialization order.
+#if _LIBCPP_STD_VER > 11
+_LIBCPP_SAFE_STATIC
+#endif
+ResourceInitHelper res_init  __attribute__((init_priority (101)));
+
+} // end namespace
+
+
+memory_resource * new_delete_resource() _NOEXCEPT {
+    return &res_init.resources.new_delete_res;
+}
+
+memory_resource * null_memory_resource() _NOEXCEPT {
+    return &res_init.resources.null_res;
+}
+
+// default_memory_resource()
+
+static memory_resource *
+__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT
+{
+#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
+    _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res =
+        ATOMIC_VAR_INIT(&res_init.resources.new_delete_res);
+    if (set) {
+        new_res = new_res ? new_res : new_delete_resource();
+        // TODO: Can a weaker ordering be used?
+        return _VSTD::atomic_exchange_explicit(
+            &__res, new_res, memory_order::memory_order_acq_rel);
+    }
+    else {
+        return _VSTD::atomic_load_explicit(
+            &__res, memory_order::memory_order_acquire);
+    }
+#elif !defined(_LIBCPP_HAS_NO_THREADS)
+    _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res;
+    static mutex res_lock;
+    if (set) {
+        new_res = new_res ? new_res : new_delete_resource();
+        lock_guard<mutex> guard(res_lock);
+        memory_resource * old_res = res;
+        res = new_res;
+        return old_res;
+    } else {
+        lock_guard<mutex> guard(res_lock);
+        return res;
+    }
+#else
+    _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res;
+    if (set) {
+        new_res = new_res ? new_res : new_delete_resource();
+        memory_resource * old_res = res;
+        res = new_res;
+        return old_res;
+    } else {
+        return res;
+    }
+#endif
+}
+
+memory_resource * get_default_resource() _NOEXCEPT
+{
+    return __default_memory_resource();
+}
+
+memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT
+{
+    return __default_memory_resource(true, __new_res);
+}
+
+// 23.12.5, mem.res.pool
+
+static size_t roundup(size_t count, size_t alignment)
+{
+    size_t mask = alignment - 1;
+    return (count + mask) & ~mask;
+}
+
+struct unsynchronized_pool_resource::__adhoc_pool::__chunk_header {
+    __chunk_header *__next_;
+    char *__start_;
+    size_t __align_;
+    size_t __allocation_size() {
+        return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this);
+    }
+};
+
+void unsynchronized_pool_resource::__adhoc_pool::__release_ptr(
+    memory_resource *upstream)
+{
+    while (__first_ != nullptr) {
+        __chunk_header *next = __first_->__next_;
+        upstream->deallocate(__first_->__start_, __first_->__allocation_size(),
+                             __first_->__align_);
+        __first_ = next;
+    }
+}
+
+void *unsynchronized_pool_resource::__adhoc_pool::__do_allocate(
+    memory_resource *upstream, size_t bytes, size_t align)
+{
+    const size_t header_size = sizeof(__chunk_header);
+    const size_t header_align = alignof(__chunk_header);
+
+    if (align < header_align)
+        align = header_align;
+
+    size_t aligned_capacity = roundup(bytes, header_align) + header_size;
+
+    void *result = upstream->allocate(aligned_capacity, align);
+
+    __chunk_header *h =
+        (__chunk_header *)((char *)result + aligned_capacity - header_size);
+    h->__next_ = __first_;
+    h->__start_ = (char *)result;
+    h->__align_ = align;
+    __first_ = h;
+    return result;
+}
+
+void unsynchronized_pool_resource::__adhoc_pool::__do_deallocate(
+    memory_resource *upstream, void *p, size_t bytes, size_t align)
+{
+    _LIBCPP_ASSERT(__first_ != nullptr, "deallocating a block that was not allocated with this allocator");
+    if (__first_->__start_ == p) {
+        __chunk_header *next = __first_->__next_;
+        upstream->deallocate(p, __first_->__allocation_size(), __first_->__align_);
+        __first_ = next;
+    } else {
+        for (__chunk_header *h = __first_; h->__next_ != nullptr; h = h->__next_) {
+            if (h->__next_->__start_ == p) {
+                __chunk_header *next = h->__next_->__next_;
+                upstream->deallocate(p, h->__next_->__allocation_size(),
+                                     h->__next_->__align_);
+                h->__next_ = next;
+                return;
+            }
+        }
+        _LIBCPP_ASSERT(false, "deallocating a block that was not allocated with this allocator");
+    }
+}
+
+class unsynchronized_pool_resource::__fixed_pool {
+    struct __chunk_header {
+        __chunk_header *__next_;
+        char *__start_;
+        size_t __align_;
+        size_t __allocation_size() {
+            return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this);
+        }
+    };
+
+    struct __vacancy_header {
+        __vacancy_header *__next_vacancy_;
+    };
+
+    __chunk_header *__first_chunk_ = nullptr;
+    __vacancy_header *__first_vacancy_ = nullptr;
+
+public:
+    explicit __fixed_pool() = default;
+
+    void __release_ptr(memory_resource *upstream)
+    {
+        __first_vacancy_ = nullptr;
+        while (__first_chunk_ != nullptr) {
+            __chunk_header *next = __first_chunk_->__next_;
+            upstream->deallocate(__first_chunk_->__start_,
+                __first_chunk_->__allocation_size(), __first_chunk_->__align_);
+            __first_chunk_ = next;
+        }
+    }
+
+    void *__try_allocate_from_vacancies()
+    {
+        if (__first_vacancy_ != nullptr) {
+            void *result = __first_vacancy_;
+            __first_vacancy_ = __first_vacancy_->__next_vacancy_;
+            return result;
+        }
+        return nullptr;
+    }
+
+    void *__allocate_in_new_chunk(
+        memory_resource *upstream, size_t block_size, size_t chunk_size)
+    {
+        _LIBCPP_ASSERT(chunk_size % block_size == 0, "");
+        static_assert(__default_alignment >= alignof(std::max_align_t), "");
+        static_assert(__default_alignment >= alignof(__chunk_header), "");
+        static_assert(__default_alignment >= alignof(__vacancy_header), "");
+
+        const size_t header_size = sizeof(__chunk_header);
+        const size_t header_align = alignof(__chunk_header);
+
+        size_t aligned_capacity = roundup(chunk_size, header_align) + header_size;
+
+        void *result = upstream->allocate(aligned_capacity, __default_alignment);
+
+        __chunk_header *h =
+            (__chunk_header *)((char *)result + aligned_capacity - header_size);
+        h->__next_ = __first_chunk_;
+        h->__start_ = (char *)result;
+        h->__align_ = __default_alignment;
+        __first_chunk_ = h;
+
+        if (chunk_size > block_size) {
+            __vacancy_header *last_vh = this->__first_vacancy_;
+            for (size_t i = block_size; i != chunk_size; i += block_size) {
+                __vacancy_header *vh = (__vacancy_header *)((char *)result + i);
+                vh->__next_vacancy_ = last_vh;
+                last_vh = vh;
+            }
+            this->__first_vacancy_ = last_vh;
+        }
+        return result;
+    }
+
+    void __evacuate(void *p)
+    {
+        __vacancy_header *vh = (__vacancy_header *)(p);
+        vh->__next_vacancy_ = __first_vacancy_;
+        __first_vacancy_ = vh;
+    }
+
+    size_t __previous_chunk_size_in_bytes() const
+    {
+        return __first_chunk_ ? __first_chunk_->__allocation_size() : 0;
+    }
+
+    static const size_t __default_alignment = alignof(max_align_t);
+};
+
+size_t unsynchronized_pool_resource::__pool_block_size(int i) const
+{
+    return size_t(1) << __log2_pool_block_size(i);
+}
+
+int unsynchronized_pool_resource::__log2_pool_block_size(int i) const
+{
+    return (i + __log2_smallest_block_size);
+}
+
+int unsynchronized_pool_resource::__pool_index(size_t bytes, size_t align) const
+{
+    if (align > alignof(std::max_align_t) || bytes > (size_t(1) << __num_fixed_pools_))
+        return __num_fixed_pools_;
+    else {
+        int i = 0;
+        bytes = (bytes > align) ? bytes : align;
+        bytes -= 1;
+        bytes >>= __log2_smallest_block_size;
+        while (bytes != 0) {
+            bytes >>= 1;
+            i += 1;
+        }
+        return i;
+    }
+}
+
+unsynchronized_pool_resource::unsynchronized_pool_resource(
+    const pool_options& opts, memory_resource* upstream)
+    : __res_(upstream), __fixed_pools_(nullptr)
+{
+    size_t largest_block_size;
+    if (opts.largest_required_pool_block == 0)
+        largest_block_size = __default_largest_block_size;
+    else if (opts.largest_required_pool_block < __smallest_block_size)
+        largest_block_size = __smallest_block_size;
+    else if (opts.largest_required_pool_block > __max_largest_block_size)
+        largest_block_size = __max_largest_block_size;
+    else
+        largest_block_size = opts.largest_required_pool_block;
+
+    if (opts.max_blocks_per_chunk == 0)
+        __options_max_blocks_per_chunk_ = __max_blocks_per_chunk;
+    else if (opts.max_blocks_per_chunk < __min_blocks_per_chunk)
+        __options_max_blocks_per_chunk_ = __min_blocks_per_chunk;
+    else if (opts.max_blocks_per_chunk > __max_blocks_per_chunk)
+        __options_max_blocks_per_chunk_ = __max_blocks_per_chunk;
+    else
+        __options_max_blocks_per_chunk_ = opts.max_blocks_per_chunk;
+
+    __num_fixed_pools_ = 1;
+    size_t capacity = __smallest_block_size;
+    while (capacity < largest_block_size) {
+        capacity <<= 1;
+        __num_fixed_pools_ += 1;
+    }
+}
+
+pool_options unsynchronized_pool_resource::options() const
+{
+    pool_options p;
+    p.max_blocks_per_chunk = __options_max_blocks_per_chunk_;
+    p.largest_required_pool_block = __pool_block_size(__num_fixed_pools_ - 1);
+    return p;
+}
+
+void unsynchronized_pool_resource::release()
+{
+    __adhoc_pool_.__release_ptr(__res_);
+    if (__fixed_pools_ != nullptr) {
+        const int n = __num_fixed_pools_;
+        for (int i=0; i < n; ++i)
+            __fixed_pools_[i].__release_ptr(__res_);
+        __res_->deallocate(__fixed_pools_,
+            __num_fixed_pools_ * sizeof(__fixed_pool), alignof(__fixed_pool));
+        __fixed_pools_ = nullptr;
+    }
+}
+
+void *unsynchronized_pool_resource::do_allocate(size_t bytes, size_t align)
+{
+    // A pointer to allocated storage (6.6.4.4.1) with a size of at least bytes.
+    // The size and alignment of the allocated memory shall meet the requirements for
+    // a class derived from memory_resource (23.12).
+    // If the pool selected for a block of size bytes is unable to satisfy the memory request
+    // from its own internal data structures, it will call upstream_resource()->allocate()
+    // to obtain more memory. If bytes is larger than that which the largest pool can handle,
+    // then memory will be allocated using upstream_resource()->allocate().
+
+    int i = __pool_index(bytes, align);
+    if (i == __num_fixed_pools_)
+        return __adhoc_pool_.__do_allocate(__res_, bytes, align);
+    else {
+        if (__fixed_pools_ == nullptr) {
+            __fixed_pools_ = (__fixed_pool*)__res_->allocate(
+                __num_fixed_pools_ * sizeof(__fixed_pool),
+                alignof(__fixed_pool)
+            );
+            __fixed_pool *first = __fixed_pools_;
+            __fixed_pool *last = __fixed_pools_ + __num_fixed_pools_;
+            for (__fixed_pool *pool = first; pool != last; ++pool)
+                ::new((void*)pool) __fixed_pool;
+        }
+        void *result = __fixed_pools_[i].__try_allocate_from_vacancies();
+        if (result == nullptr) {
+            static_assert(
+                (__max_bytes_per_chunk*5)/4 > __max_bytes_per_chunk,
+                "unsigned overflow is possible"
+            );
+            auto min = [](size_t a, size_t b) { return a < b ? a : b; };
+            auto max = [](size_t a, size_t b) { return a < b ? b : a; };
+
+            size_t prev_chunk_size_in_bytes = __fixed_pools_[i].__previous_chunk_size_in_bytes();
+            size_t prev_chunk_size_in_blocks = prev_chunk_size_in_bytes >> __log2_pool_block_size(i);
+
+            size_t chunk_size_in_blocks;
+
+            if (prev_chunk_size_in_blocks == 0) {
+                size_t min_blocks_per_chunk = max(
+                    __min_bytes_per_chunk >> __log2_pool_block_size(i),
+                    __min_blocks_per_chunk
+                );
+                chunk_size_in_blocks = min_blocks_per_chunk;
+            } else
+                chunk_size_in_blocks = (prev_chunk_size_in_blocks*5)/4;
+
+            size_t max_blocks_per_chunk = min(
+                (__max_bytes_per_chunk >> __log2_pool_block_size(i)),
+                min(
+                    __max_blocks_per_chunk,
+                    __options_max_blocks_per_chunk_
+                )
+            );
+            if (chunk_size_in_blocks > max_blocks_per_chunk)
+                chunk_size_in_blocks = max_blocks_per_chunk;
+
+            size_t block_size = __pool_block_size(i);
+
+            size_t chunk_size_in_bytes =
+                (chunk_size_in_blocks << __log2_pool_block_size(i));
+            result = __fixed_pools_[i].__allocate_in_new_chunk(
+                __res_, block_size, chunk_size_in_bytes
+            );
+        }
+        return result;
+    }
+}
+
+void unsynchronized_pool_resource::do_deallocate(
+    void* p, size_t bytes, size_t align)
+{
+    // Returns the memory at p to the pool. It is unspecified if,
+    // or under what circumstances, this operation will result in
+    // a call to upstream_resource()->deallocate().
+
+    int i = __pool_index(bytes, align);
+    if (i == __num_fixed_pools_)
+        return __adhoc_pool_.__do_deallocate(__res_, p, bytes, align);
+    else {
+        _LIBCPP_ASSERT(__fixed_pools_ != nullptr, "deallocating a block that was not allocated with this allocator");
+        __fixed_pools_[i].__evacuate(p);
+    }
+}
+
+bool synchronized_pool_resource::do_is_equal(
+    const memory_resource& other) const _NOEXCEPT
+{
+    return &other == this;
+}
+
+// 23.12.6, mem.res.monotonic.buffer
+
+void *monotonic_buffer_resource::__initial_header::__try_allocate_from_chunk(
+    size_t bytes, size_t align)
+{
+    if (!__cur_)
+        return nullptr;
+    void *new_ptr = static_cast<void*>(__cur_);
+    size_t new_capacity = (__end_ - __cur_);
+    void *aligned_ptr = _VSTD::align(align, bytes, new_ptr, new_capacity);
+    if (aligned_ptr != nullptr)
+        __cur_ = static_cast<char*>(new_ptr) + bytes;
+    return aligned_ptr;
+}
+
+void *monotonic_buffer_resource::__chunk_header::__try_allocate_from_chunk(
+    size_t bytes, size_t align)
+{
+    void *new_ptr = static_cast<void*>(__cur_);
+    size_t new_capacity = (reinterpret_cast<char*>(this) - __cur_);
+    void *aligned_ptr = _VSTD::align(align, bytes, new_ptr, new_capacity);
+    if (aligned_ptr != nullptr)
+        __cur_ = static_cast<char*>(new_ptr) + bytes;
+    return aligned_ptr;
+}
+
+void* monotonic_buffer_resource::do_allocate(size_t bytes, size_t align)
+{
+    const size_t header_size = sizeof(__chunk_header);
+    const size_t header_align = alignof(__chunk_header);
+
+    auto previous_allocation_size = [&]() {
+        if (__chunks_ != nullptr)
+            return __chunks_->__allocation_size();
+
+        size_t newsize = (__initial_.__start_ != nullptr) ?
+            (__initial_.__end_ - __initial_.__start_) : __initial_.__size_;
+
+        return roundup(newsize, header_align) + header_size;
+    };
+
+    if (void *result = __initial_.__try_allocate_from_chunk(bytes, align))
+        return result;
+    if (__chunks_ != nullptr) {
+        if (void *result = __chunks_->__try_allocate_from_chunk(bytes, align))
+            return result;
+    }
+
+    // Allocate a brand-new chunk.
+
+    if (align < header_align)
+        align = header_align;
+
+    size_t aligned_capacity = roundup(bytes, header_align) + header_size;
+    size_t previous_capacity = previous_allocation_size();
+
+    if (aligned_capacity <= previous_capacity) {
+        size_t newsize = 2 * (previous_capacity - header_size);
+        aligned_capacity = roundup(newsize, header_align) + header_size;
+    }
+
+    char *start = (char *)__res_->allocate(aligned_capacity, align);
+    __chunk_header *header =
+        (__chunk_header *)(start + aligned_capacity - header_size);
+    header->__next_ = __chunks_;
+    header->__start_ = start;
+    header->__cur_ = start;
+    header->__align_ = align;
+    __chunks_ = header;
+
+    return __chunks_->__try_allocate_from_chunk(bytes, align);
+}
+
+} // namespace pmr
+
+_LIBCPP_END_NAMESPACE_STD
Index: test/libcxx/double_include.sh.cpp
===================================================================
--- test/libcxx/double_include.sh.cpp
+++ test/libcxx/double_include.sh.cpp
@@ -89,6 +89,7 @@
 #include <map>
 #include <math.h>
 #include <memory>
+#include <memory_resource>
 #ifndef _LIBCPP_HAS_NO_THREADS
 #include <mutex>
 #endif
Index: test/libcxx/min_max_macros.sh.cpp
===================================================================
--- test/libcxx/min_max_macros.sh.cpp
+++ test/libcxx/min_max_macros.sh.cpp
@@ -147,6 +147,8 @@
 TEST_MACROS();
 #include <memory>
 TEST_MACROS();
+#include <memory_resource>
+TEST_MACROS();
 #ifndef _LIBCPP_HAS_NO_THREADS
 #include <mutex>
 TEST_MACROS();
Index: test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_piecewise_pair.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_piecewise_pair.pass.cpp
@@ -0,0 +1,173 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class U1, class U2, class ...Args1, class ...Args2>
+// void polymorphic_allocator<T>::construct(pair<T1, T2>*, piecewise_construct_t
+//                                          tuple<Args1...> x, tuple<Args2...>)
+
+// The stardard specifiers a tranformation to uses-allocator construction as
+// follows:
+//  - If uses_allocator_v<T1,memory_resource*> is false and
+//      is_constructible_v<T,Args1...> is true, then xprime is x.
+//  - Otherwise, if uses_allocator_v<T1,memory_resource*> is true and
+//      is_constructible_v<T1,allocator_arg_t,memory_resource*,Args1...> is true,
+//      then xprime is
+//      tuple_cat(make_tuple(allocator_arg, this->resource()), std::move(x)).
+//  - Otherwise, if uses_allocator_v<T1,memory_resource*> is true and
+//      is_constructible_v<T1,Args1...,memory_resource*> is true, then xprime is
+//      tuple_cat(std::move(x), make_tuple(this->resource())).
+//  - Otherwise the program is ill formed.
+//
+// The use of "xprime = tuple_cat(..., std::move(x), ...)" causes all of the
+// objects in 'x' to be copied into 'xprime'. If 'x' contains any types which
+// are stored by value this causes an unessary copy to occur. To prevent this
+//  libc++ changes this call into
+// "xprime = forward_as_tuple(..., std::get<Idx>(std::move(x))..., ...)".
+// 'xprime' contains references to the values in 'x' instead of copying them.
+
+// This test checks the number of copies incurred to the elements in
+// 'tuple<Args1...>' and 'tuple<Args2...>'.
+
+#include <memory_resource>
+#include <type_traits>
+#include <utility>
+#include <tuple>
+#include <cassert>
+#include <cstdlib>
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+template <class T>
+struct TestHarness {
+    TestResource R;
+    ex::memory_resource * M = &R;
+    ex::polymorphic_allocator<T> A = M;
+    bool constructed = false;
+    T * ptr;
+
+    TestHarness() : ptr(A.allocate(1)) {}
+
+    template <class ...Args>
+    void construct(Args&&... args) {
+        A.construct(ptr, std::forward<Args>(args)...);
+        constructed = true;
+    }
+
+    ~TestHarness() {
+        if (constructed) A.destroy(ptr);
+        A.deallocate(ptr, 1);
+    }
+};
+
+struct CountCopies {
+  int count;
+  CountCopies() : count(0) {}
+  CountCopies(CountCopies const& o) : count(o.count + 1) {}
+};
+
+struct CountCopiesAllocV1 {
+  typedef ex::polymorphic_allocator<char> allocator_type;
+  ex::memory_resource *alloc;
+  int count;
+  CountCopiesAllocV1() : alloc(nullptr), count(0) {}
+  CountCopiesAllocV1(std::allocator_arg_t, allocator_type const& a,
+                     CountCopiesAllocV1 const& o) : alloc(a.resource()), count(o.count + 1)
+  {}
+
+  CountCopiesAllocV1(CountCopiesAllocV1 const& o) : count(o.count + 1) {}
+};
+
+
+struct CountCopiesAllocV2 {
+  typedef ex::polymorphic_allocator<char> allocator_type;
+  ex::memory_resource *alloc;
+  int count;
+  CountCopiesAllocV2() : alloc(nullptr), count(0) {}
+  CountCopiesAllocV2(CountCopiesAllocV2 const& o, allocator_type const& a)
+    : alloc(a.resource()), count(o.count + 1)
+  { }
+
+  CountCopiesAllocV2(CountCopiesAllocV2 const& o) : count(o.count + 1) {}
+};
+
+
+int main(int, char**)
+{
+    {
+        using T = CountCopies;
+        using U = CountCopiesAllocV1;
+        using P = std::pair<T, U>;
+
+        std::tuple<T> t1;
+        std::tuple<U> t2;
+
+        TestHarness<P> h;
+        h.construct(std::piecewise_construct, t1, t2);
+        P const& p = *h.ptr;
+        assert(p.first.count == 2);
+        assert(p.second.count == 2);
+        assert(p.second.alloc == h.M);
+    }
+    {
+        using T = CountCopiesAllocV1;
+        using U = CountCopiesAllocV2;
+        using P = std::pair<T, U>;
+
+        std::tuple<T> t1;
+        std::tuple<U> t2;
+
+        TestHarness<P> h;
+        h.construct(std::piecewise_construct, std::move(t1), std::move(t2));
+        P const& p = *h.ptr;
+        assert(p.first.count == 2);
+        assert(p.first.alloc == h.M);
+        assert(p.second.count == 2);
+        assert(p.second.alloc == h.M);
+    }
+    {
+        using T = CountCopiesAllocV2;
+        using U = CountCopiesAllocV1;
+        using P = std::pair<T, U>;
+
+        std::tuple<T> t1;
+        std::tuple<U> t2;
+
+        TestHarness<P> h;
+        h.construct(std::piecewise_construct, std::move(t1), std::move(t2));
+        P const& p = *h.ptr;
+        assert(p.first.count == 2);
+        assert(p.first.alloc == h.M);
+        assert(p.second.count == 2);
+        assert(p.second.alloc == h.M);
+    }
+    {
+        using T = CountCopiesAllocV2;
+        using U = CountCopies;
+        using P = std::pair<T, U>;
+
+        std::tuple<T> t1;
+        std::tuple<U> t2;
+
+        TestHarness<P> h;
+        h.construct(std::piecewise_construct, t1, t2);
+        P const& p = *h.ptr;
+        assert(p.first.count == 2);
+        assert(p.first.alloc == h.M);
+        assert(p.second.count == 2);
+    }
+
+  return 0;
+}
Index: test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/db_deallocate.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/db_deallocate.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// T* polymorphic_allocator<T>::deallocate(T*, size_t size)
+
+int AssertCount = 0;
+
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++)
+#define _LIBCPP_DEBUG 0
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+int main(int, char**)
+{
+    using Alloc = ex::polymorphic_allocator<int>;
+    using Traits = std::allocator_traits<Alloc>;
+    NullResource R;
+    Alloc a(&R);
+    const std::size_t maxSize = Traits::max_size(a);
+
+    a.deallocate(nullptr, maxSize);
+    assert(AssertCount == 0);
+    a.deallocate(nullptr, maxSize + 1);
+    assert(AssertCount == 1);
+
+  return 0;
+}
Index: test/libcxx/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main(int, char**)
+{
+    globalMemCounter.reset();
+    std::pmr::monotonic_buffer_resource mono;
+
+    for (int i=0; i < 100; ++i) {
+        mono.allocate(1);
+        assert(globalMemCounter.last_new_size < 1000000000);
+        mono.release();
+        assert(globalMemCounter.checkOutstandingNewEq(0));
+    }
+
+  return 0;
+}
Index: test/libcxx/utilities/utility/mem.res/mem.res.pool/unsynchronized_buffer.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/utility/mem.res/mem.res.pool/unsynchronized_buffer.pass.cpp
@@ -0,0 +1,209 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// struct pool_options
+// class unsynchronized_pool_resource
+// class synchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+static void assert_options(const std::pmr::pool_options& actual, const std::pmr::pool_options& expected)
+{
+    assert(actual.max_blocks_per_chunk == expected.max_blocks_per_chunk);
+    assert(actual.largest_required_pool_block == expected.largest_required_pool_block);
+}
+
+void test_pool_options(std::pmr::pool_options initial, std::pmr::pool_options expected)
+{
+    std::pmr::unsynchronized_pool_resource mr(initial, std::pmr::null_memory_resource());
+    assert_options(mr.options(), expected);
+
+    std::pmr::synchronized_pool_resource mr2(initial, std::pmr::null_memory_resource());
+    assert_options(mr2.options(), expected);
+}
+
+int main(int, char**)
+{
+    test_pool_options({0, 0}, {1048576, 1048576});
+    test_pool_options({0, 1}, {1048576, 8});
+    test_pool_options({0, 2}, {1048576, 8});
+    test_pool_options({0, 4}, {1048576, 8});
+    test_pool_options({0, 8}, {1048576, 8});
+    test_pool_options({0, 16}, {1048576, 16});
+    test_pool_options({0, 32}, {1048576, 32});
+    test_pool_options({0, 1024}, {1048576, 1024});
+    test_pool_options({0, 1048576}, {1048576, 1048576});
+    test_pool_options({0, 2097152}, {1048576, 2097152});
+    test_pool_options({0, 1073741824}, {1048576, 1073741824});
+    test_pool_options({0, 2147483648}, {1048576, 1073741824});
+    test_pool_options({0, 8589934592}, {1048576, 1073741824});
+    test_pool_options({1, 0}, {16, 1048576});
+    test_pool_options({1, 1}, {16, 8});
+    test_pool_options({1, 2}, {16, 8});
+    test_pool_options({1, 4}, {16, 8});
+    test_pool_options({1, 8}, {16, 8});
+    test_pool_options({1, 16}, {16, 16});
+    test_pool_options({1, 32}, {16, 32});
+    test_pool_options({1, 1024}, {16, 1024});
+    test_pool_options({1, 1048576}, {16, 1048576});
+    test_pool_options({1, 2097152}, {16, 2097152});
+    test_pool_options({1, 1073741824}, {16, 1073741824});
+    test_pool_options({1, 2147483648}, {16, 1073741824});
+    test_pool_options({1, 8589934592}, {16, 1073741824});
+    test_pool_options({2, 0}, {16, 1048576});
+    test_pool_options({2, 1}, {16, 8});
+    test_pool_options({2, 2}, {16, 8});
+    test_pool_options({2, 4}, {16, 8});
+    test_pool_options({2, 8}, {16, 8});
+    test_pool_options({2, 16}, {16, 16});
+    test_pool_options({2, 32}, {16, 32});
+    test_pool_options({2, 1024}, {16, 1024});
+    test_pool_options({2, 1048576}, {16, 1048576});
+    test_pool_options({2, 2097152}, {16, 2097152});
+    test_pool_options({2, 1073741824}, {16, 1073741824});
+    test_pool_options({2, 2147483648}, {16, 1073741824});
+    test_pool_options({2, 8589934592}, {16, 1073741824});
+    test_pool_options({4, 0}, {16, 1048576});
+    test_pool_options({4, 1}, {16, 8});
+    test_pool_options({4, 2}, {16, 8});
+    test_pool_options({4, 4}, {16, 8});
+    test_pool_options({4, 8}, {16, 8});
+    test_pool_options({4, 16}, {16, 16});
+    test_pool_options({4, 32}, {16, 32});
+    test_pool_options({4, 1024}, {16, 1024});
+    test_pool_options({4, 1048576}, {16, 1048576});
+    test_pool_options({4, 2097152}, {16, 2097152});
+    test_pool_options({4, 1073741824}, {16, 1073741824});
+    test_pool_options({4, 2147483648}, {16, 1073741824});
+    test_pool_options({4, 8589934592}, {16, 1073741824});
+    test_pool_options({8, 0}, {16, 1048576});
+    test_pool_options({8, 1}, {16, 8});
+    test_pool_options({8, 2}, {16, 8});
+    test_pool_options({8, 4}, {16, 8});
+    test_pool_options({8, 8}, {16, 8});
+    test_pool_options({8, 16}, {16, 16});
+    test_pool_options({8, 32}, {16, 32});
+    test_pool_options({8, 1024}, {16, 1024});
+    test_pool_options({8, 1048576}, {16, 1048576});
+    test_pool_options({8, 2097152}, {16, 2097152});
+    test_pool_options({8, 1073741824}, {16, 1073741824});
+    test_pool_options({8, 2147483648}, {16, 1073741824});
+    test_pool_options({8, 8589934592}, {16, 1073741824});
+    test_pool_options({16, 0}, {16, 1048576});
+    test_pool_options({16, 1}, {16, 8});
+    test_pool_options({16, 2}, {16, 8});
+    test_pool_options({16, 4}, {16, 8});
+    test_pool_options({16, 8}, {16, 8});
+    test_pool_options({16, 16}, {16, 16});
+    test_pool_options({16, 32}, {16, 32});
+    test_pool_options({16, 1024}, {16, 1024});
+    test_pool_options({16, 1048576}, {16, 1048576});
+    test_pool_options({16, 2097152}, {16, 2097152});
+    test_pool_options({16, 1073741824}, {16, 1073741824});
+    test_pool_options({16, 2147483648}, {16, 1073741824});
+    test_pool_options({16, 8589934592}, {16, 1073741824});
+    test_pool_options({32, 0}, {32, 1048576});
+    test_pool_options({32, 1}, {32, 8});
+    test_pool_options({32, 2}, {32, 8});
+    test_pool_options({32, 4}, {32, 8});
+    test_pool_options({32, 8}, {32, 8});
+    test_pool_options({32, 16}, {32, 16});
+    test_pool_options({32, 32}, {32, 32});
+    test_pool_options({32, 1024}, {32, 1024});
+    test_pool_options({32, 1048576}, {32, 1048576});
+    test_pool_options({32, 2097152}, {32, 2097152});
+    test_pool_options({32, 1073741824}, {32, 1073741824});
+    test_pool_options({32, 2147483648}, {32, 1073741824});
+    test_pool_options({32, 8589934592}, {32, 1073741824});
+    test_pool_options({1024, 0}, {1024, 1048576});
+    test_pool_options({1024, 1}, {1024, 8});
+    test_pool_options({1024, 2}, {1024, 8});
+    test_pool_options({1024, 4}, {1024, 8});
+    test_pool_options({1024, 8}, {1024, 8});
+    test_pool_options({1024, 16}, {1024, 16});
+    test_pool_options({1024, 32}, {1024, 32});
+    test_pool_options({1024, 1024}, {1024, 1024});
+    test_pool_options({1024, 1048576}, {1024, 1048576});
+    test_pool_options({1024, 2097152}, {1024, 2097152});
+    test_pool_options({1024, 1073741824}, {1024, 1073741824});
+    test_pool_options({1024, 2147483648}, {1024, 1073741824});
+    test_pool_options({1024, 8589934592}, {1024, 1073741824});
+    test_pool_options({1048576, 0}, {1048576, 1048576});
+    test_pool_options({1048576, 1}, {1048576, 8});
+    test_pool_options({1048576, 2}, {1048576, 8});
+    test_pool_options({1048576, 4}, {1048576, 8});
+    test_pool_options({1048576, 8}, {1048576, 8});
+    test_pool_options({1048576, 16}, {1048576, 16});
+    test_pool_options({1048576, 32}, {1048576, 32});
+    test_pool_options({1048576, 1024}, {1048576, 1024});
+    test_pool_options({1048576, 1048576}, {1048576, 1048576});
+    test_pool_options({1048576, 2097152}, {1048576, 2097152});
+    test_pool_options({1048576, 1073741824}, {1048576, 1073741824});
+    test_pool_options({1048576, 2147483648}, {1048576, 1073741824});
+    test_pool_options({1048576, 8589934592}, {1048576, 1073741824});
+    test_pool_options({2097152, 0}, {1048576, 1048576});
+    test_pool_options({2097152, 1}, {1048576, 8});
+    test_pool_options({2097152, 2}, {1048576, 8});
+    test_pool_options({2097152, 4}, {1048576, 8});
+    test_pool_options({2097152, 8}, {1048576, 8});
+    test_pool_options({2097152, 16}, {1048576, 16});
+    test_pool_options({2097152, 32}, {1048576, 32});
+    test_pool_options({2097152, 1024}, {1048576, 1024});
+    test_pool_options({2097152, 1048576}, {1048576, 1048576});
+    test_pool_options({2097152, 2097152}, {1048576, 2097152});
+    test_pool_options({2097152, 1073741824}, {1048576, 1073741824});
+    test_pool_options({2097152, 2147483648}, {1048576, 1073741824});
+    test_pool_options({2097152, 8589934592}, {1048576, 1073741824});
+    test_pool_options({1073741824, 0}, {1048576, 1048576});
+    test_pool_options({1073741824, 1}, {1048576, 8});
+    test_pool_options({1073741824, 2}, {1048576, 8});
+    test_pool_options({1073741824, 4}, {1048576, 8});
+    test_pool_options({1073741824, 8}, {1048576, 8});
+    test_pool_options({1073741824, 16}, {1048576, 16});
+    test_pool_options({1073741824, 32}, {1048576, 32});
+    test_pool_options({1073741824, 1024}, {1048576, 1024});
+    test_pool_options({1073741824, 1048576}, {1048576, 1048576});
+    test_pool_options({1073741824, 2097152}, {1048576, 2097152});
+    test_pool_options({1073741824, 1073741824}, {1048576, 1073741824});
+    test_pool_options({1073741824, 2147483648}, {1048576, 1073741824});
+    test_pool_options({1073741824, 8589934592}, {1048576, 1073741824});
+    test_pool_options({2147483648, 0}, {1048576, 1048576});
+    test_pool_options({2147483648, 1}, {1048576, 8});
+    test_pool_options({2147483648, 2}, {1048576, 8});
+    test_pool_options({2147483648, 4}, {1048576, 8});
+    test_pool_options({2147483648, 8}, {1048576, 8});
+    test_pool_options({2147483648, 16}, {1048576, 16});
+    test_pool_options({2147483648, 32}, {1048576, 32});
+    test_pool_options({2147483648, 1024}, {1048576, 1024});
+    test_pool_options({2147483648, 1048576}, {1048576, 1048576});
+    test_pool_options({2147483648, 2097152}, {1048576, 2097152});
+    test_pool_options({2147483648, 1073741824}, {1048576, 1073741824});
+    test_pool_options({2147483648, 2147483648}, {1048576, 1073741824});
+    test_pool_options({2147483648, 8589934592}, {1048576, 1073741824});
+    test_pool_options({8589934592, 0}, {1048576, 1048576});
+    test_pool_options({8589934592, 1}, {1048576, 8});
+    test_pool_options({8589934592, 2}, {1048576, 8});
+    test_pool_options({8589934592, 4}, {1048576, 8});
+    test_pool_options({8589934592, 8}, {1048576, 8});
+    test_pool_options({8589934592, 16}, {1048576, 16});
+    test_pool_options({8589934592, 32}, {1048576, 32});
+    test_pool_options({8589934592, 1024}, {1048576, 1024});
+    test_pool_options({8589934592, 1048576}, {1048576, 1048576});
+    test_pool_options({8589934592, 2097152}, {1048576, 2097152});
+    test_pool_options({8589934592, 1073741824}, {1048576, 1073741824});
+    test_pool_options({8589934592, 2147483648}, {1048576, 1073741824});
+    test_pool_options({8589934592, 8589934592}, {1048576, 1073741824});
+
+  return 0;
+}
Index: test/std/language.support/support.limits/support.limits.general/memory_resource.version.pass.cpp
===================================================================
--- test/std/language.support/support.limits/support.limits.general/memory_resource.version.pass.cpp
+++ test/std/language.support/support.limits/support.limits.general/memory_resource.version.pass.cpp
@@ -1,4 +1,3 @@
-
 //===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,29 +6,50 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// <memory_resource> feature macros
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <memory_resource>
 
-/*  Constant                                    Value
-    __cpp_lib_memory_resource                   201603L
+// Test the feature test macros defined by <memory_resource>
 
+/*  Constant                     Value
+    __cpp_lib_memory_resource    201603L [C++17]
 */
 
-// XFAIL
-// #include <memory_resource>
-#include <cassert>
+#include <memory_resource>
 #include "test_macros.h"
 
-int main(int, char**)
-{
-//  ensure that the macros that are supposed to be defined in <memory_resource> are defined.
+#if TEST_STD_VER < 14
 
-/*
-#if !defined(__cpp_lib_fooby)
-# error "__cpp_lib_fooby is not defined"
-#elif __cpp_lib_fooby < 201606L
-# error "__cpp_lib_fooby has an invalid value"
-#endif
-*/
+# ifdef __cpp_lib_memory_resource
+#   error "__cpp_lib_memory_resource should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_memory_resource
+#   error "__cpp_lib_memory_resource should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifndef __cpp_lib_memory_resource
+#   error "__cpp_lib_memory_resource should be defined in c++17"
+# endif
+# if __cpp_lib_memory_resource != 201603L
+#   error "__cpp_lib_memory_resource should have the value 201603L in c++17"
+# endif
+
+#elif TEST_STD_VER > 17
+
+# ifndef __cpp_lib_memory_resource
+#   error "__cpp_lib_memory_resource should be defined in c++2a"
+# endif
+# if __cpp_lib_memory_resource != 201603L
+#   error "__cpp_lib_memory_resource should have the value 201603L in c++2a"
+# endif
+
+#endif // TEST_STD_VER > 17
 
-  return 0;
-}
+int main(int, char**) { return 0; }
Index: test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
===================================================================
--- test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -1206,17 +1206,11 @@
 #   endif
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_memory_resource
-#     error "__cpp_lib_memory_resource should be defined in c++17"
-#   endif
-#   if __cpp_lib_memory_resource != 201603L
-#     error "__cpp_lib_memory_resource should have the value 201603L in c++17"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_memory_resource
-#     error "__cpp_lib_memory_resource should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_memory_resource
+#   error "__cpp_lib_memory_resource should be defined in c++17"
+# endif
+# if __cpp_lib_memory_resource != 201603L
+#   error "__cpp_lib_memory_resource should have the value 201603L in c++17"
 # endif
 
 # ifndef __cpp_lib_node_extract
@@ -1927,17 +1921,11 @@
 #   endif
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_memory_resource
-#     error "__cpp_lib_memory_resource should be defined in c++2a"
-#   endif
-#   if __cpp_lib_memory_resource != 201603L
-#     error "__cpp_lib_memory_resource should have the value 201603L in c++2a"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_memory_resource
-#     error "__cpp_lib_memory_resource should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_memory_resource
+#   error "__cpp_lib_memory_resource should be defined in c++2a"
+# endif
+# if __cpp_lib_memory_resource != 201603L
+#   error "__cpp_lib_memory_resource should have the value 201603L in c++2a"
 # endif
 
 # ifndef __cpp_lib_node_extract
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/assign.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/assign.pass.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// polymorphic_allocator operator=(polymorphic_allocator const &) = delete
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    typedef std::pmr::polymorphic_allocator<void> T;
+    static_assert(!std::is_copy_assignable<T>::value, "");
+    static_assert(!std::is_move_assignable<T>::value, "");
+
+    return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/copy.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/copy.pass.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// polymorphic_allocator<T>::polymorphic_allocator(polymorphic_allocator const &);
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    typedef std::pmr::polymorphic_allocator<void> A1;
+    {
+        static_assert(
+            std::is_copy_constructible<A1>::value, ""
+          );
+        static_assert(
+            std::is_move_constructible<A1>::value, ""
+          );
+    }
+    // copy
+    {
+        A1 const a((std::pmr::memory_resource*)42);
+        A1 const a2(a);
+        assert(a.resource() == a2.resource());
+    }
+    // move
+    {
+        A1 a((std::pmr::memory_resource*)42);
+        A1 a2(std::move(a));
+        assert(a.resource() == a2.resource());
+        assert(a2.resource() == (std::pmr::memory_resource*)42);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/default.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/default.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// polymorphic_allocator<T>::polymorphic_allocator() noexcept
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+int main(int, char**)
+{
+    {
+        static_assert(
+            std::is_nothrow_default_constructible<ex::polymorphic_allocator<void>>::value
+          , "Must me nothrow default constructible"
+          );
+    }
+    {
+        // test that the allocator gets its resource from get_default_resource
+        TestResource R1(42);
+        ex::set_default_resource(&R1);
+
+        typedef ex::polymorphic_allocator<void> A;
+        A const a;
+        assert(a.resource() == &R1);
+
+        ex::set_default_resource(nullptr);
+        A const a2;
+        assert(a.resource() == &R1);
+        assert(a2.resource() == ex::new_delete_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/memory_resource_convert.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/memory_resource_convert.pass.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// polymorphic_allocator<T>::polymorphic_allocator(memory_resource *)
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+int main(int, char**)
+{
+    {
+        typedef ex::polymorphic_allocator<void> A;
+        static_assert(
+            std::is_convertible<decltype(nullptr), A>::value
+          , "Must be convertible"
+          );
+        static_assert(
+            std::is_convertible<ex::memory_resource *, A>::value
+          , "Must be convertible"
+          );
+    }
+    {
+        typedef ex::polymorphic_allocator<void> A;
+        TestResource R;
+        A const a(&R);
+        assert(a.resource() == &R);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/other_alloc.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.ctor/other_alloc.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class U>
+// polymorphic_allocator<T>::polymorphic_allocator(polymorphic_allocator<U> const &);
+
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+namespace ex = std::pmr;
+
+int main()
+{
+    typedef ex::polymorphic_allocator<void> A1;
+    typedef ex::polymorphic_allocator<char> A2;
+    { // Test that the conversion is implicit and noexcept.
+        static_assert(
+            std::is_convertible<A1 const &, A2>::value, ""
+          );
+        static_assert(
+            std::is_convertible<A2 const &, A1>::value, ""
+          );
+        static_assert(
+            std::is_nothrow_constructible<A1, A2 const &>::value, ""
+          );
+        static_assert(
+            std::is_nothrow_constructible<A2, A1 const &>::value, ""
+          );
+    }
+    // copy other type
+    {
+        A1 const a((ex::memory_resource*)42);
+        A2 const a2(a);
+        assert(a.resource() == a2.resource());
+        assert(a2.resource() == (ex::memory_resource*)42);
+    }
+    {
+        A1 a((ex::memory_resource*)42);
+        A2 const a2(std::move(a));
+        assert(a.resource() == a2.resource());
+        assert(a2.resource() == (ex::memory_resource*)42);
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.eq/equal.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.eq/equal.pass.cpp
@@ -0,0 +1,135 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator;
+
+// template <class T, class U>
+// bool operator==(
+//      polymorphic_allocator<T> const &
+//    , polymorphic_allocator<U> const &) noexcept
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+int main(int, char**)
+{
+    typedef ex::polymorphic_allocator<void> A1;
+    typedef ex::polymorphic_allocator<int> A2;
+    // check return types
+    {
+        A1 const a1;
+        A2 const a2;
+        static_assert(std::is_same<decltype(a1 == a2), bool>::value, "");
+        static_assert(noexcept(a1 == a2), "");
+    }
+    // equal same type (different resource)
+    {
+        TestResource d1(1);
+        TestResource d2(1);
+        A1 const a1(&d1);
+        A1 const a2(&d2);
+
+        assert(a1 == a2);
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(0));
+
+        d1.reset();
+
+        assert(a2 == a1);
+        assert(d1.checkIsEqualCalledEq(0));
+        assert(d2.checkIsEqualCalledEq(1));
+    }
+    // equal same type (same resource)
+    {
+        TestResource d1;
+        A1 const a1(&d1);
+        A1 const a2(&d1);
+
+        assert(a1 == a2);
+        assert(d1.checkIsEqualCalledEq(0));
+
+        assert(a2 == a1);
+        assert(d1.checkIsEqualCalledEq(0));
+    }
+    // equal different type (different resource)
+    {
+        TestResource d1(42);
+        TestResource d2(42);
+        A1 const a1(&d1);
+        A2 const a2(&d2);
+
+        assert(a1 == a2);
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(0));
+
+        assert(a2 == a1);
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(1));
+
+    }
+    // equal different type (same resource)
+    {
+        TestResource d1(42);
+        A1 const a1(&d1);
+        A2 const a2(&d1);
+
+        assert(a1 == a2);
+        assert(d1.checkIsEqualCalledEq(0));
+
+        assert(a2 == a1);
+        assert(d1.checkIsEqualCalledEq(0));
+
+    }
+    // not equal same type
+    {
+        TestResource d1(1);
+        TestResource d2(2);
+        A1 const a1(&d1);
+        A1 const a2(&d2);
+
+        assert(!(a1 == a2));
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(0));
+
+        d1.reset();
+
+        assert(!(a2 == a1));
+        assert(d1.checkIsEqualCalledEq(0));
+        assert(d2.checkIsEqualCalledEq(1));
+
+    }
+    // not equal different types
+    {
+        TestResource  d1;
+        TestResource1 d2;
+        A1 const a1(&d1);
+        A2 const a2(&d2);
+
+        assert(!(a1 == a2));
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(0));
+
+        d1.reset();
+
+        assert(!(a2 == a1));
+        assert(d1.checkIsEqualCalledEq(0));
+        assert(d2.checkIsEqualCalledEq(1));
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.eq/not_equal.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.eq/not_equal.pass.cpp
@@ -0,0 +1,106 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator;
+
+// template <class T>
+// bool operator!=(
+//      polymorphic_allocator<T> const &
+//    , polymorphic_allocator<T> const &) noexcept
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+int main(int, char**)
+{
+    typedef ex::polymorphic_allocator<void> A1;
+    typedef ex::polymorphic_allocator<int> A2;
+    // check return types
+    {
+        A1 const a1;
+        A2 const a2;
+        static_assert(std::is_same<decltype(a1 != a2), bool>::value, "");
+        static_assert(noexcept(a1 != a2), "");
+    }
+    // not equal same type (different resource)
+    {
+        TestResource d1(1);
+        TestResource d2(2);
+        A1 const a1(&d1);
+        A1 const a2(&d2);
+
+        assert(a1 != a2);
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(0));
+
+        d1.reset();
+
+        assert(a2 != a1);
+        assert(d1.checkIsEqualCalledEq(0));
+        assert(d2.checkIsEqualCalledEq(1));
+    }
+    // equal same type (same resource)
+    {
+        TestResource d1;
+        A1 const a1(&d1);
+        A1 const a2(&d1);
+
+        assert(!(a1 != a2));
+        assert(d1.checkIsEqualCalledEq(0));
+
+        assert(!(a2 != a1));
+        assert(d1.checkIsEqualCalledEq(0));
+    }
+    // equal same type
+    {
+        TestResource d1(1);
+        TestResource d2(1);
+        A1 const a1(&d1);
+        A1 const a2(&d2);
+
+        assert(!(a1 != a2));
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(0));
+
+        d1.reset();
+
+        assert(!(a2 != a1));
+        assert(d1.checkIsEqualCalledEq(0));
+        assert(d2.checkIsEqualCalledEq(1));
+
+    }
+    // not equal different types
+    {
+        TestResource  d1;
+        TestResource1 d2;
+        A1 const a1(&d1);
+        A2 const a2(&d2);
+
+        assert(a1 != a2);
+        assert(d1.checkIsEqualCalledEq(1));
+        assert(d2.checkIsEqualCalledEq(0));
+
+        d1.reset();
+
+        assert(a2 != a1);
+        assert(d1.checkIsEqualCalledEq(0));
+        assert(d2.checkIsEqualCalledEq(1));
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate.pass.cpp
@@ -0,0 +1,113 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// T* polymorphic_allocator<T>::allocate(size_t n)
+
+#include <memory_resource>
+#include <limits>
+#include <memory>
+#include <exception>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+template <size_t S, size_t Align>
+void testForSizeAndAlign() {
+    using T = typename std::aligned_storage<S, Align>::type;
+    TestResource R;
+    ex::polymorphic_allocator<T> a(&R);
+
+    for (int N = 1; N <= 5; ++N) {
+        auto ret = a.allocate(N);
+        assert(R.checkAlloc(ret, N * sizeof(T), alignof(T)));
+
+        a.deallocate(ret, N);
+        R.reset();
+    }
+}
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+template <size_t S>
+void testAllocForSizeThrows() {
+    using T = typename std::aligned_storage<S>::type;
+    using Alloc = ex::polymorphic_allocator<T>;
+    using Traits = std::allocator_traits<Alloc>;
+    NullResource R;
+    Alloc a(&R);
+
+    // Test that allocating exactly the max size does not throw.
+    size_t maxSize = Traits::max_size(a);
+    try {
+        a.allocate(maxSize);
+    } catch (...) {
+        assert(false);
+    }
+
+    size_t sizeTypeMax = std::numeric_limits<std::size_t>::max();
+    if (maxSize != sizeTypeMax)
+    {
+        // Test that allocating size_t(~0) throws bad alloc.
+        try {
+            a.allocate(sizeTypeMax);
+            assert(false);
+        } catch (std::exception const&) {
+        }
+
+        // Test that allocating even one more than the max size does throw.
+        size_t overSize = maxSize + 1;
+        try {
+            a.allocate(overSize);
+            assert(false);
+        } catch (std::exception const&) {
+        }
+    }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+int main(int, char**)
+{
+    {
+        ex::polymorphic_allocator<int> a;
+        static_assert(std::is_same<decltype(a.allocate(0)), int*>::value, "");
+        static_assert(!noexcept(a.allocate(0)), "");
+    }
+    {
+        constexpr std::size_t MA = alignof(std::max_align_t);
+        testForSizeAndAlign<1, 1>();
+        testForSizeAndAlign<1, 2>();
+        testForSizeAndAlign<1, MA>();
+        testForSizeAndAlign<2, 2>();
+        testForSizeAndAlign<73, alignof(void*)>();
+        testForSizeAndAlign<73, MA>();
+        testForSizeAndAlign<13, MA>();
+    }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+    {
+        testAllocForSizeThrows<1>();
+        testAllocForSizeThrows<2>();
+        testAllocForSizeThrows<4>();
+        testAllocForSizeThrows<8>();
+        testAllocForSizeThrows<16>();
+        testAllocForSizeThrows<73>();
+        testAllocForSizeThrows<13>();
+    }
+#endif
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class U1, class U2>
+// void polymorphic_allocator<T>::construct(pair<U1, U2>*)
+
+#include <memory_resource>
+#include <type_traits>
+#include <utility>
+#include <tuple>
+#include <cassert>
+#include <cstdlib>
+#include "uses_alloc_types.h"
+
+namespace ex = std::pmr;
+
+int constructed = 0;
+
+struct default_constructible
+{
+    default_constructible() : x(42)  { ++constructed; }
+    int x{0};
+};
+
+int main(int, char**)
+{
+    // pair<default_constructible, default_constructible> as T()
+    {
+        typedef default_constructible T;
+        typedef std::pair<T, T> P;
+        typedef ex::polymorphic_allocator<void> A;
+        P * ptr = (P*)std::malloc(sizeof(P));
+        A a;
+        a.construct(ptr);
+        assert(constructed == 2);
+        assert(ptr->first.x == 42);
+        assert(ptr->second.x == 42);
+        std::free(ptr);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp
@@ -0,0 +1,139 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class P1, class P2, class U1, class U2>
+// void polymorphic_allocator<T>::construct(pair<P1, P2>*, pair<U1, U2> const&)
+
+#include <memory_resource>
+#include <type_traits>
+#include <utility>
+#include <tuple>
+#include <cassert>
+#include <cstdlib>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+#include "uses_alloc_types.h"
+#include "controlled_allocators.h"
+#include "test_allocator.h"
+
+
+template <class UA1, class UA2, class TT, class UU>
+bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
+            std::pair<TT, UU> const& p)
+{
+    using P = std::pair<UA1, UA2>;
+    TestResource R;
+    std::pmr::memory_resource * M = &R;
+    std::pmr::polymorphic_allocator<P> A(M);
+    P * ptr = (P*)std::malloc(sizeof(P));
+    P * ptr2 =  (P*)std::malloc(sizeof(P));
+
+    // UNDER TEST //
+    A.construct(ptr, p);
+
+    A.construct(ptr2, std::piecewise_construct,
+                std::forward_as_tuple(p.first),
+                std::forward_as_tuple(p.second));
+    // ------- //
+
+    bool tres = checkConstruct<decltype((p.first))>(ptr->first, TExpect, M) &&
+                checkConstructionEquiv(ptr->first, ptr2->first);
+
+    bool ures = checkConstruct<decltype((p.second))>(ptr->second, UExpect, M) &&
+                checkConstructionEquiv(ptr->second, ptr2->second);
+
+    A.destroy(ptr);
+    std::free(ptr);
+    A.destroy(ptr2);
+    std::free(ptr2);
+    return tres && ures;
+
+}
+
+template <class Alloc, class TT, class UU>
+void test_pmr_uses_allocator(std::pair<TT, UU> const& p)
+{
+    {
+        using T = NotUsesAllocator<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, p)));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, 1>;
+        using U = UsesAllocatorV2<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocArg, UA_AllocLast, p)));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, 1>;
+        using U = UsesAllocatorV3<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocLast, UA_AllocArg, p)));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocArg, UA_None, p)));
+    }
+}
+
+template <class Alloc, class TT, class UU>
+void test_pmr_not_uses_allocator(std::pair<TT, UU> const& p)
+{
+    {
+        using T = NotUsesAllocator<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, p)));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, 1>;
+        using U = UsesAllocatorV2<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, p)));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, 1>;
+        using U = UsesAllocatorV3<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, p)));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, p)));
+    }
+}
+
+template <class Tp>
+struct Print;
+
+int main(int, char**)
+{
+    using PMR = std::pmr::memory_resource*;
+    using PMA = std::pmr::polymorphic_allocator<char>;
+    {
+        int x = 42;
+        int y = 42;
+        const std::pair<int, int&> p(x, y);
+        test_pmr_not_uses_allocator<PMR>(p);
+        test_pmr_uses_allocator<PMA>(p);
+    }
+    {
+        int x = 42;
+        int y = 42;
+        const std::pair<int&, int&&> p(x, std::move(y));
+        test_pmr_not_uses_allocator<PMR>(p);
+        test_pmr_uses_allocator<PMA>(p);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_rvalue.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_rvalue.pass.cpp
@@ -0,0 +1,134 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class P1, class P2, class U1, class U2>
+// void polymorphic_allocator<T>::construct(pair<P1, P2>*, pair<U1, U2> &&)
+
+#include <memory_resource>
+#include <type_traits>
+#include <utility>
+#include <tuple>
+#include <cassert>
+#include <cstdlib>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+#include "uses_alloc_types.h"
+#include "controlled_allocators.h"
+#include "test_allocator.h"
+
+
+template <class UA1, class UA2, class TT, class UU>
+bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
+            std::pair<TT, UU>&& p)
+{
+    using P = std::pair<UA1, UA2>;
+    TestResource R;
+    std::pmr::memory_resource * M = &R;
+    std::pmr::polymorphic_allocator<P> A(M);
+    P * ptr  = A.allocate(2);
+    P * ptr2 = ptr + 1;
+
+    // UNDER TEST //
+    A.construct(ptr, std::move(p));
+
+    A.construct(ptr2, std::piecewise_construct,
+                std::forward_as_tuple(std::forward<TT>(p.first)),
+                std::forward_as_tuple(std::forward<UU>(p.second)));
+    // ------- //
+
+    bool tres = checkConstruct<TT&&>(ptr->first, TExpect, M) &&
+                checkConstructionEquiv(ptr->first, ptr2->first);
+
+    bool ures = checkConstruct<UU&&>(ptr->second, UExpect, M) &&
+                checkConstructionEquiv(ptr->second, ptr2->second);
+
+    A.destroy(ptr);
+    A.destroy(ptr2);
+    A.deallocate(ptr, 2);
+    return tres && ures;
+}
+
+template <class Alloc, class TT, class UU>
+void test_pmr_uses_allocator(std::pair<TT, UU>&& p)
+{
+    {
+        using T = NotUsesAllocator<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, std::move(p))));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, 1>;
+        using U = UsesAllocatorV2<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocArg, UA_AllocLast, std::move(p))));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, 1>;
+        using U = UsesAllocatorV3<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocLast, UA_AllocArg, std::move(p))));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocArg, UA_None, std::move(p))));
+    }
+}
+
+template <class Alloc, class TT, class UU>
+void test_pmr_not_uses_allocator(std::pair<TT, UU>&& p)
+{
+    {
+        using T = NotUsesAllocator<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, std::move(p))));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, 1>;
+        using U = UsesAllocatorV2<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, std::move(p))));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, 1>;
+        using U = UsesAllocatorV3<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, std::move(p))));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None, std::move(p))));
+    }
+}
+
+int main(int, char**)
+{
+    using PMR = std::pmr::memory_resource*;
+    using PMA = std::pmr::polymorphic_allocator<char>;
+    {
+        int x = 42;
+        int y = 42;
+        std::pair<int&, int&&> p(x, std::move(y));
+        test_pmr_not_uses_allocator<PMR>(std::move(p));
+        test_pmr_uses_allocator<PMA>(std::move(p));
+    }
+    {
+        int x = 42;
+        int y = 42;
+        std::pair<int&&, int&> p(std::move(x), y);
+        test_pmr_not_uses_allocator<PMR>(std::move(p));
+        test_pmr_uses_allocator<PMA>(std::move(p));
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_values.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_values.pass.cpp
@@ -0,0 +1,140 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class P1, class P2, class U1, class U2>
+// void polymorphic_allocator<T>::construct(pair<P1, P2>*, U1&&, U2&&)
+
+#include <memory_resource>
+#include <type_traits>
+#include <utility>
+#include <tuple>
+#include <cassert>
+#include <cstdlib>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+#include "uses_alloc_types.h"
+#include "controlled_allocators.h"
+#include "test_allocator.h"
+
+
+template <class UA1, class UA2, class TT, class UU>
+bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
+            TT&& t, UU&& u)
+{
+    using P = std::pair<UA1, UA2>;
+    TestResource R;
+    std::pmr::memory_resource * M = &R;
+    std::pmr::polymorphic_allocator<P> A(M);
+    P * ptr = (P*)std::malloc(sizeof(P));
+    P * ptr2 = (P*)std::malloc(sizeof(P));
+
+    // UNDER TEST //
+    A.construct(ptr, std::forward<TT>(t), std::forward<UU>(u));
+    A.construct(ptr2, std::piecewise_construct,
+                      std::forward_as_tuple(std::forward<TT>(t)),
+                      std::forward_as_tuple(std::forward<UU>(u)));
+    // ------- //
+
+    bool tres = checkConstruct<TT&&>(ptr->first, TExpect, M) &&
+                checkConstructionEquiv(ptr->first, ptr2->first);
+
+    bool ures = checkConstruct<UU&&>(ptr->second, UExpect, M) &&
+                checkConstructionEquiv(ptr->second, ptr2->second);
+
+    A.destroy(ptr);
+    A.destroy(ptr2);
+    std::free(ptr);
+    std::free(ptr2);
+    return tres && ures;
+}
+
+template <class Alloc, class TT, class UU>
+void test_pmr_uses_allocator(TT&& t, UU&& u)
+{
+    {
+        using T = NotUsesAllocator<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, 1>;
+        using U = UsesAllocatorV2<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocArg, UA_AllocLast,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, 1>;
+        using U = UsesAllocatorV3<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocLast, UA_AllocArg,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_AllocArg, UA_None,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+}
+
+template <class Alloc, class TT, class UU>
+void test_pmr_not_uses_allocator(TT&& t, UU&& u)
+{
+    {
+        using T = NotUsesAllocator<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, 1>;
+        using U = UsesAllocatorV2<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, 1>;
+        using U = UsesAllocatorV3<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, 1>;
+        using U = NotUsesAllocator<Alloc, 1>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::forward<TT>(t), std::forward<UU>(u))));
+    }
+}
+
+int main(int, char**)
+{
+    using PMR = std::pmr::memory_resource*;
+    using PMA = std::pmr::polymorphic_allocator<char>;
+    {
+        int x = 42;
+        int y = 42;
+        test_pmr_not_uses_allocator<PMR>(x, std::move(y));
+        test_pmr_uses_allocator<PMA>(x, std::move(y));
+    }
+    {
+        int x = 42;
+        const int y = 42;
+        test_pmr_not_uses_allocator<PMR>(std::move(x), y);
+        test_pmr_uses_allocator<PMA>(std::move(x), y);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_piecewise_pair.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_piecewise_pair.pass.cpp
@@ -0,0 +1,154 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class U1, class U2, class ...Args1, class ...Args2>
+// void polymorphic_allocator<T>::construct(pair<U1, U2>*, piecewise_construct_t
+//                                          tuple<Args1...>, tuple<Args2...>)
+
+#include <memory_resource>
+#include <type_traits>
+#include <utility>
+#include <tuple>
+#include <cassert>
+#include <cstdlib>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+#include "uses_alloc_types.h"
+#include "controlled_allocators.h"
+#include "test_allocator.h"
+
+template <class T, class U, class ...TTuple, class ...UTuple>
+bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
+            std::tuple<TTuple...> ttuple, std::tuple<UTuple...> utuple)
+{
+    using P = std::pair<T, U>;
+    TestResource R;
+    std::pmr::memory_resource * M = &R;
+    std::pmr::polymorphic_allocator<P> A(M);
+    P * ptr = A.allocate(1);
+
+    // UNDER TEST //
+    A.construct(ptr, std::piecewise_construct, std::move(ttuple), std::move(utuple));
+    // ------- //
+    bool tres = checkConstruct<TTuple&&...>(ptr->first, TExpect, M);
+    bool ures = checkConstruct<UTuple&&...>(ptr->second, UExpect, M);
+
+    A.destroy(ptr);
+    A.deallocate(ptr, 1);
+    return tres && ures;
+}
+
+template <class Alloc, class ...TTypes, class ...UTypes>
+void test_pmr_uses_allocator(std::tuple<TTypes...> ttuple, std::tuple<UTypes...> utuple)
+{
+    {
+        using T = NotUsesAllocator<Alloc, sizeof...(TTypes)>;
+        using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::move(ttuple), std::move(utuple))));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, sizeof...(TTypes)>;
+        using U = UsesAllocatorV2<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_AllocArg, UA_AllocLast,
+                             std::move(ttuple), std::move(utuple))));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, sizeof...(TTypes)>;
+        using U = UsesAllocatorV3<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_AllocLast, UA_AllocArg,
+                             std::move(ttuple), std::move(utuple))));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, sizeof...(TTypes)>;
+        using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_AllocArg, UA_None,
+                             std::move(ttuple), std::move(utuple))));
+    }
+}
+
+template <class Alloc, class ...TTypes, class ...UTypes>
+void test_pmr_not_uses_allocator(std::tuple<TTypes...> ttuple, std::tuple<UTypes...> utuple)
+{
+    {
+        using T = NotUsesAllocator<Alloc, sizeof...(TTypes)>;
+        using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::move(ttuple), std::move(utuple))));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, sizeof...(TTypes)>;
+        using U = UsesAllocatorV2<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::move(ttuple), std::move(utuple))));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, sizeof...(TTypes)>;
+        using U = UsesAllocatorV3<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::move(ttuple), std::move(utuple))));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, sizeof...(TTypes)>;
+        using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
+        assert((doTest<T, U>(UA_None, UA_None,
+                             std::move(ttuple), std::move(utuple))));
+    }
+}
+
+int main(int, char**)
+{
+    using PMR = std::pmr::memory_resource*;
+    using PMA = std::pmr::polymorphic_allocator<char>;
+    {
+        std::tuple<> t1;
+        test_pmr_not_uses_allocator<PMR>(t1, t1);
+        test_pmr_uses_allocator<PMA>(t1, t1);
+    }
+    {
+        std::tuple<int> t1(42);
+        std::tuple<> t2;
+        test_pmr_not_uses_allocator<PMR>(t1, t2);
+        test_pmr_not_uses_allocator<PMR>(t2, t1);
+        test_pmr_uses_allocator<PMA>(t1, t2);
+        test_pmr_uses_allocator<PMA>(t2, t1);
+    }
+    {
+        std::tuple<int> t1(42);
+        int x = 55;
+        double dx = 42.42;
+        std::tuple<int&, double&&> t2(x, std::move(dx));
+        test_pmr_not_uses_allocator<PMR>(           t1, std::move(t2));
+        test_pmr_not_uses_allocator<PMR>(std::move(t2),            t1);
+        test_pmr_uses_allocator<PMA>(           t1, std::move(t2));
+        test_pmr_uses_allocator<PMA>(std::move(t2),            t1);
+    }
+    {
+        void* xptr = nullptr;
+        long y = 4242;
+        std::tuple<int, long const&, void*&> t1(42, y, xptr);
+        int x = 55;
+        double dx = 42.42;
+        const char* s = "hello World";
+        std::tuple<int&, double&&, const char*> t2(x, std::move(dx), s);
+        test_pmr_not_uses_allocator<PMR>(           t1, std::move(t2));
+        test_pmr_not_uses_allocator<PMR>(std::move(t2),            t1);
+        test_pmr_uses_allocator<PMA>(           t1, std::move(t2));
+        test_pmr_uses_allocator<PMA>(std::move(t2),            t1);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_piecewise_pair_evil.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_piecewise_pair_evil.pass.cpp
@@ -0,0 +1,141 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class U1, class U2, class ...Args1, class ...Args2>
+// void polymorphic_allocator<T>::construct(pair<U1, U2>*, piecewise_construct_t
+//                                          tuple<Args1...>, tuple<Args2...>)
+
+#include <memory_resource>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <cassert>
+#include <cstdlib>
+
+#include "test_macros.h"
+
+template <class T>
+struct EvilAlloc {
+    explicit EvilAlloc() : inner_(std::pmr::null_memory_resource()) {}
+
+    EvilAlloc(std::pmr::polymorphic_allocator<T> & a) : inner_(a) {}
+    EvilAlloc(std::pmr::polymorphic_allocator<T> && a) : inner_(a) {}
+    EvilAlloc(std::pmr::polymorphic_allocator<T> const & a) = delete;
+    EvilAlloc(std::pmr::polymorphic_allocator<T> const && a) = delete;
+
+    using value_type = T;
+    template <class U> EvilAlloc(EvilAlloc<U> const & rhs) : inner_(rhs.inner_) {}
+
+    std::pmr::polymorphic_allocator<T> inner_;
+};
+
+struct WidgetV0 {
+    WidgetV0(int v) : value_(v) {}
+
+    bool holds(int v, const std::pmr::polymorphic_allocator<char>&) const {
+        return value_ == v;
+    }
+private:
+    int value_;
+};
+
+struct WidgetV1 {
+    using allocator_type = EvilAlloc<char>;
+
+    WidgetV1(int v) : value_(v), alloc_() {}
+    WidgetV1(std::allocator_arg_t, EvilAlloc<char> a, int v) : value_(v), alloc_(a) {}
+
+    bool holds(int v, const std::pmr::polymorphic_allocator<char>& a) const {
+        return value_ == v && alloc_.inner_ == a;
+    }
+private:
+    int value_;
+    EvilAlloc<char> alloc_;
+};
+
+struct WidgetV2 {
+    using allocator_type = EvilAlloc<char>;
+
+    WidgetV2(int v) : value_(v), alloc_() {}
+    WidgetV2(int v, EvilAlloc<char> a) : value_(v), alloc_(a) {}
+
+    bool holds(int v, std::pmr::polymorphic_allocator<char> a) const {
+        return value_ == v && alloc_.inner_ == a;
+    }
+private:
+    int value_;
+    EvilAlloc<char> alloc_;
+};
+
+struct WidgetV3 {
+    using allocator_type = EvilAlloc<char>;
+
+    WidgetV3(int v) : value_(v), alloc_() {}
+    WidgetV3(std::allocator_arg_t, EvilAlloc<char> a, int v) : value_(v), alloc_(a) {}
+    WidgetV3(int v, EvilAlloc<char> a) : value_(v), alloc_(a) {}
+
+    bool holds(int v, std::pmr::polymorphic_allocator<char> a) const {
+        return value_ == v && alloc_.inner_ == a;
+    }
+private:
+    int value_;
+    EvilAlloc<char> alloc_;
+};
+
+static_assert(std::uses_allocator<WidgetV1, EvilAlloc<char>>::value, "");
+static_assert(std::uses_allocator<WidgetV2, EvilAlloc<char>>::value, "");
+static_assert(std::uses_allocator<WidgetV3, EvilAlloc<char>>::value, "");
+static_assert(std::uses_allocator<WidgetV1, std::pmr::polymorphic_allocator<char>>::value, "");
+static_assert(std::uses_allocator<WidgetV2, std::pmr::polymorphic_allocator<char>>::value, "");
+static_assert(std::uses_allocator<WidgetV3, std::pmr::polymorphic_allocator<char>>::value, "");
+
+template<class W1, class W2>
+void test_evil()
+{
+    using PMA = std::pmr::polymorphic_allocator<char>;
+    PMA pma(std::pmr::new_delete_resource());
+    {
+        using Pair = std::pair<W1, W2>;
+        void *where = std::malloc(sizeof (Pair));
+        Pair *p = (Pair *)where;
+        pma.construct(p, std::piecewise_construct, std::make_tuple(42), std::make_tuple(42));
+        assert(p->first.holds(42, pma));
+        assert(p->second.holds(42, pma));
+        pma.destroy(p);
+        std::free(where);
+    }
+}
+
+int main(int, char**)
+{
+    test_evil<WidgetV0, WidgetV0>();
+    test_evil<WidgetV0, WidgetV1>();
+    test_evil<WidgetV0, WidgetV2>();
+    test_evil<WidgetV0, WidgetV3>();
+    test_evil<WidgetV1, WidgetV0>();
+    test_evil<WidgetV1, WidgetV1>();
+    test_evil<WidgetV1, WidgetV2>();
+    test_evil<WidgetV1, WidgetV3>();
+    test_evil<WidgetV2, WidgetV0>();
+    test_evil<WidgetV2, WidgetV1>();
+    test_evil<WidgetV2, WidgetV2>();
+    test_evil<WidgetV2, WidgetV3>();
+    test_evil<WidgetV3, WidgetV0>();
+    test_evil<WidgetV3, WidgetV1>();
+    test_evil<WidgetV3, WidgetV2>();
+    test_evil<WidgetV3, WidgetV3>();
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_types.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_types.pass.cpp
@@ -0,0 +1,190 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class U, class ...Args>
+// void polymorphic_allocator<T>::construct(U *, Args &&...)
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+#include <cstdlib>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+#include "uses_alloc_types.h"
+#include "controlled_allocators.h"
+#include "test_allocator.h"
+
+template <class T>
+struct PMATest {
+    TestResource R;
+    std::pmr::polymorphic_allocator<T> A;
+    T* ptr;
+    bool constructed;
+
+    PMATest() : A(&R), ptr(A.allocate(1)), constructed(false) {}
+
+    template <class ...Args>
+    void construct(Args&&... args) {
+        A.construct(ptr, std::forward<Args>(args)...);
+        constructed = true;
+    }
+
+    ~PMATest() {
+        if (constructed) A.destroy(ptr);
+        A.deallocate(ptr, 1);
+    }
+};
+
+template <class T, class ...Args>
+bool doTest(UsesAllocatorType UAExpect, Args&&... args)
+{
+    PMATest<T> TH;
+    // UNDER TEST //
+    TH.construct(std::forward<Args>(args)...);
+    return checkConstruct<Args&&...>(*TH.ptr, UAExpect, &TH.R);
+    // ------- //
+}
+
+
+template <class T, class ...Args>
+bool doTestUsesAllocV0(Args&&... args)
+{
+    PMATest<T> TH;
+    // UNDER TEST //
+    TH.construct(std::forward<Args>(args)...);
+    return checkConstruct<Args&&...>(*TH.ptr, UA_None);
+    // -------- //
+}
+
+
+template <class T, class EAlloc, class ...Args>
+bool doTestUsesAllocV1(EAlloc const& ealloc, Args&&... args)
+{
+    PMATest<T> TH;
+    // UNDER TEST //
+    TH.construct(std::allocator_arg, ealloc, std::forward<Args>(args)...);
+    return checkConstruct<Args&&...>(*TH.ptr, UA_AllocArg, ealloc);
+    // -------- //
+}
+
+template <class T, class EAlloc, class ...Args>
+bool doTestUsesAllocV2(EAlloc const& ealloc, Args&&... args)
+{
+    PMATest<T> TH;
+    // UNDER TEST //
+    TH.construct(std::forward<Args>(args)..., ealloc);
+    return checkConstruct<Args&&...>(*TH.ptr, UA_AllocLast, ealloc);
+    // -------- //
+}
+
+template <class Alloc, class ...Args>
+void test_pmr_uses_alloc(Args&&... args)
+{
+    TestResource R(12435);
+    std::pmr::memory_resource* M = &R;
+    {
+        // NotUsesAllocator provides valid signatures for each uses-allocator
+        // construction but does not supply the required allocator_type typedef.
+        // Test that we can call these constructors manually without
+        // polymorphic_allocator interfering.
+        using T = NotUsesAllocator<Alloc, sizeof...(Args)>;
+        assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
+        assert((doTestUsesAllocV1<T>(M, std::forward<Args>(args)...)));
+        assert((doTestUsesAllocV2<T>(M, std::forward<Args>(args)...)));
+    }
+    {
+        // Test T(std::allocator_arg_t, Alloc const&, Args...) construction
+        using T = UsesAllocatorV1<Alloc, sizeof...(Args)>;
+        assert((doTest<T>(UA_AllocArg, std::forward<Args>(args)...)));
+    }
+    {
+        // Test T(Args..., Alloc const&) construction
+        using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
+        assert((doTest<T>(UA_AllocLast, std::forward<Args>(args)...)));
+    }
+    {
+        // Test that T(std::allocator_arg_t, Alloc const&, Args...) construction
+        // is preferred when T(Args..., Alloc const&) is also available.
+        using T = UsesAllocatorV3<Alloc, sizeof...(Args)>;
+        assert((doTest<T>(UA_AllocArg, std::forward<Args>(args)...)));
+    }
+}
+
+// Test that polymorphic_allocator does not prevent us from manually
+// doing non-pmr uses-allocator construction.
+template <class Alloc, class AllocObj, class ...Args>
+void test_non_pmr_uses_alloc(AllocObj const& A, Args&&... args)
+{
+    {
+        using T = NotUsesAllocator<Alloc, sizeof...(Args)>;
+        assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
+        assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
+        assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
+    }
+    {
+        using T = UsesAllocatorV1<Alloc, sizeof...(Args)>;
+        assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
+        assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
+    }
+    {
+        using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
+        assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
+        assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
+    }
+    {
+        using T = UsesAllocatorV3<Alloc, sizeof...(Args)>;
+        assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
+        assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
+        assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
+    }
+}
+
+int main(int, char**)
+{
+    using PMR = std::pmr::memory_resource*;
+    using PMA = std::pmr::polymorphic_allocator<char>;
+    using STDA = std::allocator<char>;
+    using TESTA = test_allocator<char>;
+
+    int value = 42;
+    const int cvalue = 43;
+    {
+        test_pmr_uses_alloc<PMA>();
+        test_pmr_uses_alloc<PMA>(value);
+        test_pmr_uses_alloc<PMA>(cvalue);
+        test_pmr_uses_alloc<PMA>(cvalue, std::move(value));
+    }
+    {
+        STDA std_alloc;
+        TESTA test_alloc(42);
+        PMR mem_res = std::pmr::new_delete_resource();
+
+        test_non_pmr_uses_alloc<PMR>(mem_res);
+        test_non_pmr_uses_alloc<STDA>(std_alloc);
+        test_non_pmr_uses_alloc<TESTA>(test_alloc);
+        test_non_pmr_uses_alloc<PMR>(mem_res, value);
+        test_non_pmr_uses_alloc<STDA>(std_alloc, value);
+        test_non_pmr_uses_alloc<TESTA>(test_alloc, value);
+        test_non_pmr_uses_alloc<PMR>(mem_res, cvalue);
+        test_non_pmr_uses_alloc<STDA>(std_alloc, cvalue);
+        test_non_pmr_uses_alloc<TESTA>(test_alloc, cvalue);
+        test_non_pmr_uses_alloc<PMR>(mem_res, cvalue, std::move(cvalue));
+        test_non_pmr_uses_alloc<STDA>(std_alloc, cvalue, std::move(value));
+        test_non_pmr_uses_alloc<TESTA>(test_alloc, cvalue, std::move(value));
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/deallocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/deallocate.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// T* polymorphic_allocator<T>::deallocate(T*, size_t size)
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+template <size_t S, size_t Align>
+void testForSizeAndAlign() {
+    using T = typename std::aligned_storage<S, Align>::type;
+
+    TestResource R;
+    ex::polymorphic_allocator<T> a(&R);
+
+    for (int N = 1; N <= 5; ++N) {
+        auto ret = a.allocate(N);
+        assert(R.checkAlloc(ret, N * sizeof(T), alignof(T)));
+
+        a.deallocate(ret, N);
+        assert(R.checkDealloc(ret, N * sizeof(T), alignof(T)));
+
+        R.reset();
+    }
+}
+
+int main(int, char**)
+{
+    {
+        ex::polymorphic_allocator<int> a;
+        static_assert(
+            std::is_same<decltype(a.deallocate(nullptr, 0)), void>::value, "");
+    }
+    {
+        constexpr std::size_t MA = alignof(std::max_align_t);
+        testForSizeAndAlign<1, 1>();
+        testForSizeAndAlign<1, 2>();
+        testForSizeAndAlign<1, MA>();
+        testForSizeAndAlign<2, 2>();
+        testForSizeAndAlign<73, alignof(void*)>();
+        testForSizeAndAlign<73, MA>();
+        testForSizeAndAlign<13, MA>();
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/destroy.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/destroy.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// template <class U>
+// void polymorphic_allocator<T>::destroy(U * ptr);
+
+#include <memory_resource>
+#include <type_traits>
+#include <new>
+#include <cassert>
+#include <cstdlib>
+
+namespace ex = std::pmr;
+
+int count = 0;
+
+struct destroyable
+{
+    destroyable() { ++count; }
+    ~destroyable() { --count; }
+};
+
+int main(int, char**)
+{
+    typedef ex::polymorphic_allocator<double> A;
+    {
+        A a;
+        static_assert(
+            std::is_same<decltype(a.destroy((destroyable*)nullptr)), void>::value,
+            "");
+    }
+    {
+        destroyable * ptr = ::new (std::malloc(sizeof(destroyable))) destroyable();
+        assert(count == 1);
+        A{}.destroy(ptr);
+        assert(count == 0);
+        std::free(ptr);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/resource.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/resource.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// memory_resource *
+// polymorphic_allocator<T>::resource() const
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+namespace ex = std::pmr;
+
+int main(int, char**)
+{
+    typedef ex::polymorphic_allocator<void> A;
+    {
+        A const a;
+        static_assert(
+            std::is_same<decltype(a.resource()), ex::memory_resource*>::value
+          , ""
+          );
+    }
+    {
+        ex::memory_resource * mptr = (ex::memory_resource*)42;
+        A const a(mptr);
+        assert(a.resource() == mptr);
+    }
+    {
+        A const a(nullptr);
+        assert(a.resource() == nullptr);
+        assert(a.resource() == nullptr);
+    }
+    {
+        A const a;
+        assert(a.resource() == ex::get_default_resource());
+    }
+    {
+        ex::memory_resource * mptr = (ex::memory_resource*)42;
+        ex::set_default_resource(mptr);
+        A const a;
+        assert(a.resource() == mptr);
+        assert(a.resource() == ex::get_default_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/select_on_container_copy_construction.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/select_on_container_copy_construction.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// template <class T> class polymorphic_allocator
+
+// polymorphic_allocator
+// polymorphic_allocator<T>::select_on_container_copy_construction() const
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+namespace ex = std::pmr;
+
+int main(int, char**)
+{
+    typedef ex::polymorphic_allocator<void> A;
+    {
+        A const a;
+        static_assert(
+            std::is_same<decltype(a.select_on_container_copy_construction()), A>::value,
+            "");
+    }
+    {
+        ex::memory_resource * mptr = (ex::memory_resource*)42;
+        A const a(mptr);
+        assert(a.resource() == mptr);
+        A const other = a.select_on_container_copy_construction();
+        assert(other.resource() == ex::get_default_resource());
+        assert(a.resource() == mptr);
+    }
+    {
+        ex::memory_resource * mptr = (ex::memory_resource*)42;
+        ex::set_default_resource(mptr);
+        A const a(nullptr);
+        assert(a.resource() == nullptr);
+        A const other = a.select_on_container_copy_construction();
+        assert(other.resource() == ex::get_default_resource());
+        assert(other.resource() == mptr);
+        assert(a.resource() == nullptr);
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_deque_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_deque_synop.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <deque>
+
+// namespace std::pmr {
+// template <class T>
+// using deque =
+//     ::std::deque<T, polymorphic_allocator<T>>
+//
+// } // namespace std::pmr
+
+#include <deque>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    using StdDeque = std::deque<int, std::pmr::polymorphic_allocator<int>>;
+    using PmrDeque = std::pmr::deque<int>;
+    static_assert(std::is_same<StdDeque, PmrDeque>::value, "");
+    PmrDeque d;
+    assert(d.get_allocator().resource() == std::pmr::get_default_resource());
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_forward_list_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_forward_list_synop.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <forward_list>
+
+// namespace std::pmr {
+// template <class T>
+// using forward_list =
+//     ::std::forward_list<T, polymorphic_allocator<T>>
+//
+// } // namespace std::pmr
+
+#include <forward_list>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    using StdForwardList = std::forward_list<int, std::pmr::polymorphic_allocator<int>>;
+    using PmrForwardList = std::pmr::forward_list<int>;
+    static_assert(std::is_same<StdForwardList, PmrForwardList>::value, "");
+    PmrForwardList d;
+    assert(d.get_allocator().resource() == std::pmr::get_default_resource());
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_list_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_list_synop.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <list>
+
+// namespace std::pmr {
+// template <class T>
+// using list =
+//     ::std::list<T, polymorphic_allocator<T>>
+//
+// } // namespace std::pmr
+
+#include <list>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    using StdList = std::list<int, std::pmr::polymorphic_allocator<int>>;
+    using PmrList = std::pmr::list<int>;
+    static_assert(std::is_same<StdList, PmrList>::value, "");
+    PmrList d;
+    assert(d.get_allocator().resource() == std::pmr::get_default_resource());
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_list_synop2.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_list_synop2.pass.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: c++17
+
+// <list>
+
+// namespace std::pmr {
+//
+// typedef ... list
+//
+// } // namespace std::pmr
+
+#include <list>
+
+int main(int, char**)
+{
+    {
+        // Check that std::pmr::list is usable without <memory_resource>.
+        std::pmr::list<int> l;
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_map_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_map_synop.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <map>
+
+// namespace std::pmr {
+// template <class K, class V, class Compare = less<Key> >
+// using map =
+//     ::std::map<K, V, Compare, polymorphic_allocator<pair<const K, V>>>
+//
+// template <class K, class V, class Compare = less<Key> >
+// using multimap =
+//     ::std::multimap<K, V, Compare, polymorphic_allocator<pair<const K, V>>>
+//
+// } // namespace std::pmr
+
+#include <map>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    using K = int;
+    using V = char;
+    using DC = std::less<int>;
+    using OC = std::greater<int>;
+    using P = std::pair<const K, V>;
+    {
+        using StdMap = std::map<K, V, DC, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::map<K, V>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        using StdMap = std::map<K, V, OC, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::map<K, V, OC>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        std::pmr::map<int, int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+    {
+        using StdMap = std::multimap<K, V, DC, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::multimap<K, V>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        using StdMap = std::multimap<K, V, OC, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::multimap<K, V, OC>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        std::pmr::multimap<int, int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_regex_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_regex_synop.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <regex>
+
+// namespace std::pmr {
+//
+//  template <class BidirectionalIterator>
+//  using match_results =
+//    std::match_results<BidirectionalIterator,
+//                       polymorphic_allocator<sub_match<BidirectionalIterator>>>;
+//
+//  typedef match_results<const char*> cmatch;
+//  typedef match_results<const wchar_t*> wcmatch;
+//  typedef match_results<string::const_iterator> smatch;
+//  typedef match_results<wstring::const_iterator> wsmatch;
+//
+// } // namespace std::pmr
+
+#include <regex>
+#include <type_traits>
+#include <cassert>
+
+template <class Iter, class PmrTypedef>
+void test_match_result_typedef() {
+    using StdMR = std::match_results<Iter, std::pmr::polymorphic_allocator<std::sub_match<Iter>>>;
+    using PmrMR = std::pmr::match_results<Iter>;
+    static_assert(std::is_same<StdMR, PmrMR>::value, "");
+    static_assert(std::is_same<PmrMR, PmrTypedef>::value, "");
+}
+
+int main(int, char**)
+{
+    {
+        test_match_result_typedef<const char*, std::pmr::cmatch>();
+        test_match_result_typedef<const wchar_t*, std::pmr::wcmatch>();
+        test_match_result_typedef<std::pmr::string::const_iterator, std::pmr::smatch>();
+        test_match_result_typedef<std::pmr::wstring::const_iterator, std::pmr::wsmatch>();
+    }
+    {
+        // Check that std::match_results has been included and is complete.
+        std::pmr::smatch s;
+        assert(s.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_set_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_set_synop.pass.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <set>
+
+// namespace std::pmr {
+// template <class V, class Compare = less<V> >
+// using set =
+//     ::std::set<V, Compare, polymorphic_allocator<V>>
+//
+// template <class V, class Compare = less<V> >
+// using multiset =
+//     ::std::multiset<V, Compare, polymorphic_allocator<V>>
+//
+// } // namespace std::pmr
+
+#include <set>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    using V = char;
+    using DC = std::less<V>;
+    using OC = std::greater<V>;
+    {
+        using StdSet = std::set<V, DC, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::set<V>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        using StdSet = std::set<V, OC, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::set<V, OC>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        std::pmr::set<int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+    {
+        using StdSet = std::multiset<V, DC, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::multiset<V>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        using StdSet = std::multiset<V, OC, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::multiset<V, OC>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        std::pmr::multiset<int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_string_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_string_synop.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <string>
+
+// namespace std::pmr {
+// template <class Char, class Traits = ...>
+// using basic_string =
+//     ::std::basic_string<Char, Traits, polymorphic_allocator<Char>>
+//
+// typedef ... string
+// typedef ... u16string
+// typedef ... u32string
+// typedef ... wstring
+//
+// } // namespace std::pmr
+
+#include <string>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "constexpr_char_traits.h"
+
+namespace pmr = std::pmr;
+
+template <class Char, class PmrTypedef>
+void test_string_typedef() {
+    using StdStr = std::basic_string<Char, std::char_traits<Char>,
+                                     std::pmr::polymorphic_allocator<Char>>;
+    using PmrStr = std::pmr::basic_string<Char>;
+    static_assert(std::is_same<StdStr, PmrStr>::value, "");
+    static_assert(std::is_same<PmrStr, PmrTypedef>::value, "");
+}
+
+template <class Char, class Traits>
+void test_basic_string_alias() {
+    using StdStr = std::basic_string<Char, Traits,
+                                     std::pmr::polymorphic_allocator<Char>>;
+    using PmrStr = std::pmr::basic_string<Char, Traits>;
+    static_assert(std::is_same<StdStr, PmrStr>::value, "");
+}
+
+int main(int, char**)
+{
+    {
+        test_string_typedef<char,     std::pmr::string>();
+        test_string_typedef<wchar_t,  std::pmr::wstring>();
+        test_string_typedef<char16_t, std::pmr::u16string>();
+        test_string_typedef<char32_t, std::pmr::u32string>();
+    }
+    {
+        test_basic_string_alias<char,    constexpr_char_traits<char>>();
+        test_basic_string_alias<wchar_t, constexpr_char_traits<wchar_t>>();
+        test_basic_string_alias<char16_t, constexpr_char_traits<char16_t>>();
+        test_basic_string_alias<char32_t, constexpr_char_traits<char32_t>>();
+    }
+    {
+        // Check that std::basic_string has been included and is complete.
+        std::pmr::string s;
+        assert(s.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_string_synop2.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_string_synop2.pass.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: c++17
+
+// <string>
+
+// namespace std::pmr {
+//
+// typedef ... string
+// typedef ... u16string
+// typedef ... u32string
+// typedef ... wstring
+//
+// } // namespace std::pmr
+
+#include <string>
+
+int main(int, char**)
+{
+    {
+        // Check that std::pmr::string is usable without <memory_resource>.
+        std::pmr::string s;
+        std::pmr::wstring ws;
+        std::pmr::u16string u16s;
+        std::pmr::u32string u32s;
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_unordered_map_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_unordered_map_synop.pass.cpp
@@ -0,0 +1,85 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <unordered_map>
+
+// namespace std::pmr {
+// template <class K, class V, class H = hash<K>, class P = equal_to<K> >
+// using unordered_map =
+//     ::std::unordered_map<K, V, H, P, polymorphic_allocator<pair<const K, V>>>
+//
+// template <class K, class V,  class H = hash<K>, class P = equal_to<K> >
+// using unordered_multimap =
+//     ::std::unordered_multimap<K, V, H, P, polymorphic_allocator<pair<const K, V>>>
+//
+// } // namespace std::pmr
+
+#include <unordered_map>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+template <class T>
+struct MyHash : std::hash<T> {};
+
+template <class T>
+struct MyPred : std::equal_to<T> {};
+
+int main(int, char**)
+{
+    using K = int;
+    using V = char;
+    using DH = std::hash<K>;
+    using MH = MyHash<K>;
+    using DP = std::equal_to<K>;
+    using MP = MyPred<K>;
+    using P = std::pair<const K, V>;
+    {
+        using StdMap = std::unordered_map<K, V, DH, DP, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::unordered_map<K, V>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        using StdMap = std::unordered_map<K, V, MH, DP, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::unordered_map<K, V, MH>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        using StdMap = std::unordered_map<K, V, MH, MP, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::unordered_map<K, V, MH, MP>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        std::pmr::unordered_map<int, int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+    {
+        using StdMap = std::unordered_multimap<K, V, DH, DP, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::unordered_multimap<K, V>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        using StdMap = std::unordered_multimap<K, V, MH, DP, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::unordered_multimap<K, V, MH>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        using StdMap = std::unordered_multimap<K, V, MH, MP, std::pmr::polymorphic_allocator<P>>;
+        using PmrMap = std::pmr::unordered_multimap<K, V, MH, MP>;
+        static_assert(std::is_same<StdMap, PmrMap>::value, "");
+    }
+    {
+        std::pmr::unordered_multimap<int, int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_unordered_set_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_unordered_set_synop.pass.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <unordered_set>
+
+// namespace std::pmr {
+// template <class V, class H = hash<V>, class P = equal_to<V> >
+// using unordered_set =
+//     ::std::unordered_set<V, H, P, polymorphic_allocator<V>>
+//
+// template <class V,  class H = hash<V>, class P = equal_to<V> >
+// using unordered_multiset =
+//     ::std::unordered_multiset<V, H, P, polymorphic_allocator<V>>
+//
+// } // namespace std::pmr
+
+#include <unordered_set>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+template <class T>
+struct MyHash : std::hash<T> {};
+
+template <class T>
+struct MyPred : std::equal_to<T> {};
+
+int main(int, char**)
+{
+    using V = char;
+    using DH = std::hash<V>;
+    using MH = MyHash<V>;
+    using DP = std::equal_to<V>;
+    using MP = MyPred<V>;
+    {
+        using StdSet = std::unordered_set<V, DH, DP, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::unordered_set<V>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        using StdSet = std::unordered_set<V, MH, DP, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::unordered_set<V, MH>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        using StdSet = std::unordered_set<V, MH, MP, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::unordered_set<V, MH, MP>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        std::pmr::unordered_set<int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+    {
+        using StdSet = std::unordered_multiset<V, DH, DP, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::unordered_multiset<V>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        using StdSet = std::unordered_multiset<V, MH, DP, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::unordered_multiset<V, MH>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        using StdSet = std::unordered_multiset<V, MH, MP, std::pmr::polymorphic_allocator<V>>;
+        using PmrSet = std::pmr::unordered_multiset<V, MH, MP>;
+        static_assert(std::is_same<StdSet, PmrSet>::value, "");
+    }
+    {
+        std::pmr::unordered_multiset<int> m;
+        assert(m.get_allocator().resource() == std::pmr::get_default_resource());
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.aliases/header_vector_synop.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.aliases/header_vector_synop.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <vector>
+
+// namespace std::pmr {
+// template <class T>
+// using vector =
+//     ::std::vector<T, polymorphic_allocator<T>>
+//
+// } // namespace std::pmr
+
+#include <vector>
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main(int, char**)
+{
+    using StdVector = std::vector<int, std::pmr::polymorphic_allocator<int>>;
+    using PmrVector = std::pmr::vector<int>;
+    static_assert(std::is_same<StdVector, PmrVector>::value, "");
+    PmrVector d;
+    assert(d.get_allocator().resource() == std::pmr::get_default_resource());
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.global/default_resource.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.global/default_resource.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+//-----------------------------------------------------------------------------
+// TESTING memory_resource * get_default_resource() noexcept;
+//         memory_resource * set_default_resource(memory_resource*) noexcept;
+//
+// Concerns:
+//  A) 'get_default_resource()' returns a non-null memory_resource pointer.
+//  B) 'get_default_resource()' returns the value set by the last call to
+//     'set_default_resource(...)' and 'new_delete_resource()' if no call
+//     to 'set_default_resource(...)' has occurred.
+//  C) 'set_default_resource(...)' returns the previous value of the default
+//     resource.
+//  D) 'set_default_resource(T* p)' for a non-null 'p' sets the default resource
+//     to be 'p'.
+//  E) 'set_default_resource(null)' sets the default resource to
+//     'new_delete_resource()'.
+//  F) 'get_default_resource' and 'set_default_resource' are noexcept.
+
+
+#include <memory_resource>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+using namespace std::pmr;
+
+int main(int, char**) {
+    TestResource R;
+    { // Test (A) and (B)
+        memory_resource* p = get_default_resource();
+        assert(p != nullptr);
+        assert(p == new_delete_resource());
+        assert(p == get_default_resource());
+    }
+    { // Test (C) and (D)
+        memory_resource *expect = &R;
+        memory_resource *old = set_default_resource(expect);
+        assert(old != nullptr);
+        assert(old == new_delete_resource());
+
+        memory_resource *p = get_default_resource();
+        assert(p != nullptr);
+        assert(p == expect);
+        assert(p == get_default_resource());
+    }
+    { // Test (E)
+        memory_resource* old = set_default_resource(nullptr);
+        assert(old == &R);
+        memory_resource* p = get_default_resource();
+        assert(p != nullptr);
+        assert(p == new_delete_resource());
+        assert(p == get_default_resource());
+    }
+    { // Test (F)
+        static_assert(noexcept(get_default_resource()),
+                      "get_default_resource() must be noexcept");
+
+        static_assert(noexcept(set_default_resource(nullptr)),
+                      "set_default_resource() must be noexcept");
+    }
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.global/new_delete_resource.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.global/new_delete_resource.pass.cpp
@@ -0,0 +1,103 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// memory_resource * new_delete_resource()
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "count_new.h"
+
+namespace ex = std::pmr;
+
+struct assert_on_compare : public ex::memory_resource
+{
+protected:
+    virtual void * do_allocate(size_t, size_t)
+    { assert(false); }
+
+    virtual void do_deallocate(void *, size_t, size_t)
+    { assert(false); }
+
+    virtual bool do_is_equal(ex::memory_resource const &) const noexcept
+    { assert(false); }
+};
+
+void test_return()
+{
+    {
+        static_assert(std::is_same<
+            decltype(ex::new_delete_resource()), ex::memory_resource*
+          >::value, "");
+    }
+    // assert not null
+    {
+        assert(ex::new_delete_resource());
+    }
+    // assert same return value
+    {
+        assert(ex::new_delete_resource() == ex::new_delete_resource());
+    }
+}
+
+void test_equality()
+{
+    // Same object
+    {
+        ex::memory_resource & r1 = *ex::new_delete_resource();
+        ex::memory_resource & r2 = *ex::new_delete_resource();
+        // check both calls returned the same object
+        assert(&r1 == &r2);
+        // check for proper equality semantics
+        assert(r1 == r2);
+        assert(r2 == r1);
+        assert(!(r1 != r2));
+        assert(!(r2 != r1));
+    }
+    // Different types
+    {
+        ex::memory_resource & r1 = *ex::new_delete_resource();
+        assert_on_compare c;
+        ex::memory_resource & r2 = c;
+        assert(r1 != r2);
+        assert(!(r1 == r2));
+    }
+}
+
+void test_allocate_deallocate()
+{
+    ex::memory_resource & r1 = *ex::new_delete_resource();
+
+    globalMemCounter.reset();
+
+    void *ret = r1.allocate(50);
+    assert(ret);
+    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkLastNewSizeEq(50));
+
+    r1.deallocate(ret, 1);
+    assert(globalMemCounter.checkOutstandingNewEq(0));
+    assert(globalMemCounter.checkDeleteCalledEq(1));
+
+}
+
+int main(int, char**)
+{
+    static_assert(noexcept(ex::new_delete_resource()), "Must be noexcept");
+    test_return();
+    test_equality();
+    test_allocate_deallocate();
+
+  return 0;
+}
Index: test/std/utilities/utility/mem.res/mem.res.global/null_memory_resource.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.global/null_memory_resource.pass.cpp
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// memory_resource * null_memory_resource()
+
+#include <memory_resource>
+#include <new>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.h"
+
+namespace ex = std::pmr;
+
+struct assert_on_compare : public ex::memory_resource
+{
+protected:
+    virtual void * do_allocate(size_t, size_t)
+    { assert(false); }
+
+    virtual void do_deallocate(void *, size_t, size_t)
+    { assert(false); }
+
+    virtual bool do_is_equal(ex::memory_resource const &) const noexcept
+    { assert(false); }
+};
+
+void test_return()
+{
+    {
+        static_assert(std::is_same<
+            decltype(ex::null_memory_resource()), ex::memory_resource*
+          >::value, "");
+    }
+    // Test that the returned value is not null
+    {
+        assert(ex::null_memory_resource());
+    }
+    // Test the same value is returned by repeated calls.
+    {
+        assert(ex::null_memory_resource() == ex::null_memory_resource());
+    }
+}
+
+void test_equality()
+{
+    // Same object
+    {
+        ex::memory_resource & r1 = *ex::null_memory_resource();
+        ex::memory_resource & r2 = *ex::null_memory_resource();
+        // check both calls returned the same object
+        assert(&r1 == &r2);
+        // check for proper equality semantics
+        assert(r1 == r2);
+        assert(r2 == r1);
+        assert(!(r1 != r2));
+        assert(!(r2 != r1));
+        // check the is_equal method
+        assert(r1.is_equal(r2));
+        assert(r2.is_equal(r1));
+    }
+    // Different types
+    {
+        ex::memory_resource & r1 = *ex::null_memory_resource();
+        assert_on_compare c;
+        ex::memory_resource & r2 = c;
+        assert(r1 != r2);
+        assert(!(r1 == r2));
+        assert(!r1.is_equal(r2));
+    }
+}
+
+void test_allocate()
+{
+#ifndef TEST_HAS_NO_EXCEPTIONS
+    DisableAllocationGuard g; // null_memory_resource shouldn't allocate.
+    try {
+        ex::null_memory_resource()->allocate(1);
+        assert(false);
+    } catch (std::bad_alloc const &) {
+       // do nothing
+    } catch (...) {
+        assert(false);
+    }
+#endif
+}
+
+void test_deallocate()
+{
+    globalMemCounter.reset();
+
+    int x = 42;
+    ex::null_memory_resource()->deallocate(nullptr, 0);
+    ex::null_memory_resource()->deallocate(&x, 0);
+
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+    assert(globalMemCounter.checkDeleteArrayCalledEq(0));
+}
+
+int main()
+{
+    test_return();
+    test_equality();
+    test_allocate();
+    test_deallocate();
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.ctor/copy_move.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.ctor/copy_move.pass.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// monotonic_buffer_resource(monotonic_buffer_resource const&) = delete;
+// monotonic_buffer_resource& operator=(monotonic_buffer_resource const&) = delete;
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+int main()
+{
+    using MBR = std::pmr::monotonic_buffer_resource;
+    static_assert(!std::is_copy_constructible<MBR>::value, "");
+    static_assert(!std::is_move_constructible<MBR>::value, "");
+    static_assert(!std::is_copy_assignable<MBR>::value, "");
+    static_assert(!std::is_move_assignable<MBR>::value, "");
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.ctor/with_default_resource.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.ctor/with_default_resource.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+int main()
+{
+    std::pmr::memory_resource *expected = std::pmr::null_memory_resource();
+    std::pmr::set_default_resource(expected);
+    {
+        char buffer[16];
+        std::pmr::monotonic_buffer_resource r1;
+        std::pmr::monotonic_buffer_resource r2(16);
+        std::pmr::monotonic_buffer_resource r3(buffer, sizeof buffer);
+        assert(r1.upstream_resource() == expected);
+        assert(r2.upstream_resource() == expected);
+        assert(r3.upstream_resource() == expected);
+    }
+
+    expected = std::pmr::new_delete_resource();
+    std::pmr::set_default_resource(expected);
+    {
+        char buffer[16];
+        std::pmr::monotonic_buffer_resource r1;
+        std::pmr::monotonic_buffer_resource r2(16);
+        std::pmr::monotonic_buffer_resource r3(buffer, sizeof buffer);
+        assert(r1.upstream_resource() == expected);
+        assert(r2.upstream_resource() == expected);
+        assert(r3.upstream_resource() == expected);
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.ctor/without_buffer.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.ctor/without_buffer.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+    // Constructing a monotonic_buffer_resource should not cause allocations
+    // by itself; the resource should wait to allocate until an allocation is
+    // requested.
+
+    globalMemCounter.reset();
+    std::pmr::set_default_resource(std::pmr::new_delete_resource());
+
+    std::pmr::monotonic_buffer_resource r1;
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    std::pmr::monotonic_buffer_resource r2(1024);
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    std::pmr::monotonic_buffer_resource r3(1024, std::pmr::new_delete_resource());
+    assert(globalMemCounter.checkNewCalledEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_deallocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_deallocate.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+    {
+        globalMemCounter.reset();
+
+        std::pmr::monotonic_buffer_resource mono1(std::pmr::new_delete_resource());
+        std::pmr::memory_resource & r1 = mono1;
+
+        void *ret = r1.allocate(50);
+        assert(ret);
+        assert(globalMemCounter.checkNewCalledGreaterThan(0));
+        assert(globalMemCounter.checkDeleteCalledEq(0));
+
+        // mem.res.monotonic.buffer 1.2
+        // A call to deallocate has no effect, thus the amount of memory
+        // consumed increases monotonically until the resource is destroyed.
+        // Check that deallocate is a no-op
+        r1.deallocate(ret, 50);
+        assert(globalMemCounter.checkDeleteCalledEq(0));
+
+        mono1.release();
+        assert(globalMemCounter.checkDeleteCalledEq(1));
+        assert(globalMemCounter.checkOutstandingNewEq(0));
+
+        globalMemCounter.reset();
+
+        ret = r1.allocate(500);
+        assert(ret);
+        assert(globalMemCounter.checkNewCalledGreaterThan(0));
+        assert(globalMemCounter.checkDeleteCalledEq(0));
+
+        // Check that the destructor calls release()
+    }
+    assert(globalMemCounter.checkDeleteCalledEq(1));
+    assert(globalMemCounter.checkOutstandingNewEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_exception_safety.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_exception_safety.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+struct repointable_resource : public std::pmr::memory_resource
+{
+    std::pmr::memory_resource *which;
+
+    explicit repointable_resource(std::pmr::memory_resource *res) : which(res) {}
+
+protected:
+    virtual void *do_allocate(size_t size, size_t align)
+    { return which->allocate(size, align); }
+
+    virtual void do_deallocate(void *p, size_t size, size_t align)
+    { return which->deallocate(p, size, align); }
+
+    virtual bool do_is_equal(std::pmr::memory_resource const &rhs) const noexcept
+    { return which->is_equal(rhs); }
+};
+
+int main()
+{
+    globalMemCounter.reset();
+    repointable_resource upstream(std::pmr::new_delete_resource());
+    alignas(16) char buffer[64];
+    std::pmr::monotonic_buffer_resource mono1(buffer, sizeof buffer, &upstream);
+    std::pmr::memory_resource & r1 = mono1;
+
+    void *res = r1.allocate(64, 16);
+    assert(res == buffer);
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    res = r1.allocate(64, 16);
+    assert(res != buffer);
+    assert(globalMemCounter.checkNewCalledEq(1));
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+    const size_t last_new_size = globalMemCounter.last_new_size;
+
+    upstream.which = std::pmr::null_memory_resource();
+    try {
+        res = r1.allocate(last_new_size, 16);
+        assert(false);
+    } catch (const std::bad_alloc&) {
+        // we expect this
+    }
+    assert(globalMemCounter.checkNewCalledEq(1));
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+
+    upstream.which = std::pmr::new_delete_resource();
+    res = r1.allocate(last_new_size, 16);
+    assert(res != buffer);
+    assert(globalMemCounter.checkNewCalledEq(2));
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+
+    mono1.release();
+    assert(globalMemCounter.checkNewCalledEq(2));
+    assert(globalMemCounter.checkDeleteCalledEq(2));
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_initial_buffer.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_initial_buffer.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+    globalMemCounter.reset();
+    char buffer[100];
+    std::pmr::monotonic_buffer_resource mono1((void *)buffer, sizeof buffer, std::pmr::new_delete_resource());
+    std::pmr::memory_resource & r1 = mono1;
+
+    // Check that construction with a buffer does not allocate anything from the upstream
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    // Check that an allocation that fits in the buffer does not allocate anything from the upstream
+    void *ret = r1.allocate(50);
+    assert(ret);
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    // Check a second allocation
+    ret = r1.allocate(20);
+    assert(ret);
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    r1.deallocate(ret, 50);
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+
+    // Check an allocation that doesn't fit in the original buffer
+    ret = r1.allocate(50);
+    assert(ret);
+    assert(globalMemCounter.checkNewCalledEq(1));
+
+    r1.deallocate(ret, 50);
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+
+    mono1.release();
+    assert(globalMemCounter.checkDeleteCalledEq(1));
+    assert(globalMemCounter.checkOutstandingNewEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_underaligned_buffer.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_underaligned_buffer.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+    globalMemCounter.reset();
+    {
+        alignas(4) char buffer[17];
+        std::pmr::monotonic_buffer_resource mono1(buffer + 1, 16, std::pmr::new_delete_resource());
+        std::pmr::memory_resource & r1 = mono1;
+
+        void *ret = r1.allocate(1, 1);
+        assert(ret == buffer + 1);
+        mono1.release();
+
+        ret = r1.allocate(1, 2);
+        assert(ret == buffer + 2);
+        mono1.release();
+
+        ret = r1.allocate(1, 4);
+        assert(ret == buffer + 4);
+        mono1.release();
+
+        // Test a size that is just big enough to fit in the buffer,
+        // but can't fit if it's aligned.
+        ret = r1.allocate(16, 1);
+        assert(ret == buffer + 1);
+        mono1.release();
+
+        assert(globalMemCounter.checkNewCalledEq(0));
+        ret = r1.allocate(16, 2);
+        assert(globalMemCounter.checkNewCalledEq(1));
+        assert(globalMemCounter.last_new_size >= 16);
+        // assert(globalMemCounter.last_new_align >= 2);
+        mono1.release();
+        assert(globalMemCounter.checkDeleteCalledEq(1));
+        // assert(globalMemCounter.last_new_align == globalMemCounter.last_delete_align);
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_zero_sized_buffer.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_zero_sized_buffer.pass.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+    globalMemCounter.reset();
+    {
+        char buffer[100];
+        std::pmr::monotonic_buffer_resource mono1((void *)buffer, 0, std::pmr::new_delete_resource());
+        std::pmr::memory_resource & r1 = mono1;
+
+        void *ret = r1.allocate(1, 1);
+        assert(ret != nullptr);
+        assert(globalMemCounter.checkNewCalledEq(1));
+    }
+    assert(globalMemCounter.checkDeleteCalledEq(1));
+
+    globalMemCounter.reset();
+    {
+        std::pmr::monotonic_buffer_resource mono1(nullptr, 0, std::pmr::new_delete_resource());
+        std::pmr::memory_resource & r1 = mono1;
+
+        void *ret = r1.allocate(1, 1);
+        assert(ret != nullptr);
+        assert(globalMemCounter.checkNewCalledEq(1));
+    }
+    assert(globalMemCounter.checkDeleteCalledEq(1));
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+void test_geometric_progression()
+{
+    // mem.res.monotonic.buffer 1.3
+    // Each additional buffer is larger than the previous one, following a
+    // geometric progression.
+
+    globalMemCounter.reset();
+    std::pmr::monotonic_buffer_resource mono1(100, std::pmr::new_delete_resource());
+    std::pmr::memory_resource & r1 = mono1;
+
+    assert(globalMemCounter.checkNewCalledEq(0));
+    size_t next_buffer_size = 100;
+    void *ret = r1.allocate(10, 1);
+    assert(ret != nullptr);
+    assert(globalMemCounter.checkNewCalledEq(1));
+    assert(globalMemCounter.last_new_size >= next_buffer_size);
+    next_buffer_size = globalMemCounter.last_new_size + 1;
+
+    int new_called = 1;
+    while (new_called < 5) {
+        ret = r1.allocate(10, 1);
+        if (globalMemCounter.new_called > new_called) {
+            assert(globalMemCounter.new_called == new_called + 1);
+            assert(globalMemCounter.last_new_size >= next_buffer_size);
+            next_buffer_size = globalMemCounter.last_new_size + 1;
+            new_called += 1;
+        }
+    }
+}
+
+int main()
+{
+    test_geometric_progression();
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_overaligned_request.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_overaligned_request.pass.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+#ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
+
+    globalMemCounter.reset();
+    std::pmr::monotonic_buffer_resource mono1(1024, std::pmr::new_delete_resource());
+    std::pmr::memory_resource & r1 = mono1;
+
+    constexpr size_t big_alignment = 8 * alignof(std::max_align_t);
+    static_assert(big_alignment > 4);
+
+    void *ret = r1.allocate(2048, big_alignment);
+    assert(ret != nullptr);
+    assert(globalMemCounter.checkNewCalledEq(1));
+    assert(globalMemCounter.last_new_size >= 2048);
+    assert(globalMemCounter.last_new_align >= big_alignment);
+
+    // Check that a single highly aligned allocation request doesn't
+    // permanently "poison" the resource to allocate only super-aligned
+    // blocks of memory.
+    ret = r1.allocate(globalMemCounter.last_new_size, 4);
+    assert(ret != nullptr);
+    assert(globalMemCounter.checkNewCalledEq(2));
+    assert(globalMemCounter.last_new_align >= 4);
+    assert(globalMemCounter.last_new_align < big_alignment);
+
+#endif
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+void test(size_t initial_buffer_size)
+{
+    globalMemCounter.reset();
+
+    std::pmr::monotonic_buffer_resource mono1(
+        initial_buffer_size,
+        std::pmr::new_delete_resource()
+    );
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    mono1.allocate(1, 1);
+    assert(globalMemCounter.checkNewCalledEq(1));
+    assert(globalMemCounter.last_new_size >= initial_buffer_size);
+
+    mono1.allocate(initial_buffer_size - 1, 1);
+    assert(globalMemCounter.checkNewCalledEq(1));
+}
+
+int main()
+{
+    test(1);
+    test(8);
+    test(10);
+    test(100);
+    test(256);
+    test(1000);
+    test(1024);
+    test(1000000);
+    assert(globalMemCounter.checkOutstandingNewEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/equality.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/equality.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class monotonic_buffer_resource
+
+#include <memory_resource>
+#include <new>
+#include <type_traits>
+#include <cassert>
+
+struct assert_on_compare : public std::pmr::memory_resource
+{
+protected:
+    virtual void * do_allocate(size_t, size_t)
+    { assert(false); }
+
+    virtual void do_deallocate(void *, size_t, size_t)
+    { assert(false); }
+
+    virtual bool do_is_equal(std::pmr::memory_resource const &) const noexcept
+    { assert(false); }
+};
+
+int main()
+{
+    // Same object
+    {
+        std::pmr::monotonic_buffer_resource r1;
+        std::pmr::monotonic_buffer_resource r2;
+        assert(r1 == r1);
+        assert(r1 != r2);
+
+        std::pmr::memory_resource & p1 = r1;
+        std::pmr::memory_resource & p2 = r2;
+        assert(p1 == p1);
+        assert(p1 != p2);
+        assert(p1 == r1);
+        assert(r1 == p1);
+        assert(p1 != r2);
+        assert(r2 != p1);
+    }
+    // Different types
+    {
+        std::pmr::monotonic_buffer_resource mono1;
+        std::pmr::memory_resource & r1 = mono1;
+        assert_on_compare c;
+        std::pmr::memory_resource & r2 = c;
+        assert(r1 != r2);
+        assert(!(r1 == r2));
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/ctor_does_not_allocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/ctor_does_not_allocate.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class synchronized_pool_resource
+// class unsynchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+template<class PoolResource>
+void test()
+{
+    // Constructing a pool resource should not cause allocations
+    // by itself; the resource should wait to allocate until an
+    // allocation is requested.
+
+    globalMemCounter.reset();
+    std::pmr::set_default_resource(std::pmr::new_delete_resource());
+
+    PoolResource r1;
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    PoolResource r2(std::pmr::pool_options{ 1024, 2048 });
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    PoolResource r3(std::pmr::pool_options{ 1024, 2048 }, std::pmr::new_delete_resource());
+    assert(globalMemCounter.checkNewCalledEq(0));
+}
+
+int main()
+{
+    test<std::pmr::unsynchronized_pool_resource>();
+    test<std::pmr::synchronized_pool_resource>();
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/sync_with_default_resource.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/sync_with_default_resource.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class synchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+int main()
+{
+    std::pmr::memory_resource *expected = std::pmr::null_memory_resource();
+    std::pmr::set_default_resource(expected);
+    {
+        std::pmr::pool_options opts { 0, 0 };
+        std::pmr::synchronized_pool_resource r1;
+        std::pmr::synchronized_pool_resource r2(opts);
+        assert(r1.upstream_resource() == expected);
+        assert(r2.upstream_resource() == expected);
+    }
+
+    expected = std::pmr::new_delete_resource();
+    std::pmr::set_default_resource(expected);
+    {
+        std::pmr::pool_options opts { 1024, 2048 };
+        std::pmr::synchronized_pool_resource r1;
+        std::pmr::synchronized_pool_resource r2(opts);
+        assert(r1.upstream_resource() == expected);
+        assert(r2.upstream_resource() == expected);
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/unsync_with_default_resource.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/unsync_with_default_resource.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class unsynchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+int main()
+{
+    std::pmr::memory_resource *expected = std::pmr::null_memory_resource();
+    std::pmr::set_default_resource(expected);
+    {
+        std::pmr::pool_options opts { 0, 0 };
+        std::pmr::unsynchronized_pool_resource r1;
+        std::pmr::unsynchronized_pool_resource r2(opts);
+        assert(r1.upstream_resource() == expected);
+        assert(r2.upstream_resource() == expected);
+    }
+
+    expected = std::pmr::new_delete_resource();
+    std::pmr::set_default_resource(expected);
+    {
+        std::pmr::pool_options opts { 1024, 2048 };
+        std::pmr::unsynchronized_pool_resource r1;
+        std::pmr::unsynchronized_pool_resource r2(opts);
+        assert(r1.upstream_resource() == expected);
+        assert(r2.upstream_resource() == expected);
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/equality.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/equality.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class synchronized_pool_resource
+// class unsynchronized_pool_resource
+
+#include <memory_resource>
+#include <new>
+#include <type_traits>
+#include <cassert>
+
+#include "count_new.h"
+
+class assert_on_compare : public std::pmr::memory_resource
+{
+    void * do_allocate(size_t, size_t) override
+    { assert(false); }
+
+    void do_deallocate(void *, size_t, size_t) override
+    { assert(false); }
+
+    bool do_is_equal(std::pmr::memory_resource const &) const noexcept override
+    { assert(false); }
+};
+
+template<class PoolResource>
+void test()
+{
+    // Same type
+    {
+        PoolResource pr1;
+        PoolResource pr2;
+        assert(pr1 == pr1);
+        assert(pr1 != pr2);
+
+        std::pmr::memory_resource & mr1 = pr1;
+        std::pmr::memory_resource & mr2 = pr2;
+        assert(mr1 == mr1);
+        assert(mr1 != mr2);
+        assert(mr1 == pr1);
+        assert(pr1 == mr1);
+        assert(mr1 != pr2);
+        assert(pr2 != mr1);
+    }
+    // Different types
+    {
+        PoolResource pr1;
+        std::pmr::memory_resource & mr1 = pr1;
+        assert_on_compare c;
+        std::pmr::memory_resource & mr2 = c;
+        assert(mr1 != mr2);
+        assert(!(mr1 == mr2));
+    }
+}
+
+int main()
+{
+    test<std::pmr::synchronized_pool_resource>();
+    test<std::pmr::unsynchronized_pool_resource>();
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class synchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+    {
+        globalMemCounter.reset();
+
+        std::pmr::synchronized_pool_resource sync1(std::pmr::new_delete_resource());
+        std::pmr::memory_resource & r1 = sync1;
+
+        void *ret = r1.allocate(50);
+        assert(ret);
+        assert(globalMemCounter.checkNewCalledGreaterThan(0));
+        assert(globalMemCounter.checkDeleteCalledEq(0));
+
+        r1.deallocate(ret, 50);
+        sync1.release();
+        assert(globalMemCounter.checkDeleteCalledGreaterThan(0));
+        assert(globalMemCounter.checkOutstandingNewEq(0));
+
+        globalMemCounter.reset();
+
+        ret = r1.allocate(500);
+        assert(ret);
+        assert(globalMemCounter.checkNewCalledGreaterThan(0));
+        assert(globalMemCounter.checkDeleteCalledEq(0));
+
+        // Check that the destructor calls release()
+    }
+    assert(globalMemCounter.checkDeleteCalledGreaterThan(0));
+    assert(globalMemCounter.checkOutstandingNewEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_overaligned_request.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_overaligned_request.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class synchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+bool is_aligned_to(void *p, size_t alignment)
+{
+    void *p2 = p;
+    size_t space = 1;
+    void *result = std::align(alignment, 1, p2, space);
+    return (result == p);
+}
+
+int main()
+{
+#ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
+
+    globalMemCounter.reset();
+    std::pmr::pool_options opts { 1, 1024 };
+    std::pmr::synchronized_pool_resource sync1(opts, std::pmr::new_delete_resource());
+    std::pmr::memory_resource & r1 = sync1;
+
+    constexpr size_t big_alignment = 8 * alignof(std::max_align_t);
+    static_assert(big_alignment > 4);
+
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    void *ret = r1.allocate(2048, big_alignment);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, big_alignment));
+    assert(globalMemCounter.checkNewCalledGreaterThan(0));
+
+    ret = r1.allocate(16, 4);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, 4));
+    assert(globalMemCounter.checkNewCalledGreaterThan(1));
+
+#endif
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_reuse_blocks.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_reuse_blocks.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class synchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+static bool is_aligned_to(void *p, size_t alignment)
+{
+    void *p2 = p;
+    size_t space = 1;
+    void *result = std::align(alignment, 1, p2, space);
+    return (result == p);
+}
+
+int main()
+{
+    globalMemCounter.reset();
+    std::pmr::pool_options opts { 1, 256 };
+    std::pmr::synchronized_pool_resource sync1(opts, std::pmr::new_delete_resource());
+    std::pmr::memory_resource & r1 = sync1;
+
+    void *ret = r1.allocate(8);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, 8));
+    assert(globalMemCounter.checkNewCalledGreaterThan(0));
+    int new_called = globalMemCounter.new_called;
+
+    // After deallocation, the pool for 8-byte blocks should have at least one vacancy.
+    r1.deallocate(ret, 8);
+    assert(globalMemCounter.new_called == new_called);
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+
+    // This should return an existing block from the pool: no new allocations.
+    ret = r1.allocate(8);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, 8));
+    assert(globalMemCounter.new_called == new_called);
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_deallocate_matches_allocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_deallocate_matches_allocate.pass.cpp
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class synchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+#include <vector>
+
+struct allocation_record {
+    size_t bytes;
+    size_t align;
+    explicit allocation_record(size_t b, size_t a) : bytes(b), align(a) {}
+    bool operator==(const allocation_record& rhs) const {
+        return (bytes == rhs.bytes) && (align == rhs.align);
+    }
+    bool operator<(const allocation_record& rhs) const {
+        if (bytes != rhs.bytes) return (bytes < rhs.bytes);
+        return (align < rhs.align);
+    }
+};
+
+class test_resource : public std::pmr::memory_resource {
+    void *do_allocate(size_t bytes, size_t align) override {
+        void *result = std::pmr::new_delete_resource()->allocate(bytes, align);
+        successful_allocations.emplace_back(bytes, align);
+        return result;
+    }
+    void do_deallocate(void *p, size_t bytes, size_t align) override {
+        deallocations.emplace_back(bytes, align);
+        return std::pmr::new_delete_resource()->deallocate(p, bytes, align);
+    }
+    bool do_is_equal(const std::pmr::memory_resource&) const noexcept override {
+        return false;
+    }
+public:
+    std::vector<allocation_record> successful_allocations;
+    std::vector<allocation_record> deallocations;
+};
+
+template<class F>
+void test_allocation_pattern(F do_pattern)
+{
+    test_resource tr;
+    std::pmr::pool_options opts { 0, 256 };
+    std::pmr::synchronized_pool_resource spr(opts, &tr);
+
+    try {
+        do_pattern(spr);
+    } catch (const std::bad_alloc&) {}
+    spr.release();
+
+    assert(tr.successful_allocations.size() == tr.deallocations.size());
+    std::sort(tr.successful_allocations.begin(), tr.successful_allocations.end());
+    std::sort(tr.deallocations.begin(), tr.deallocations.end());
+    assert(tr.successful_allocations == tr.deallocations);
+}
+
+template<size_t Bytes, size_t Align>
+auto foo() {
+    return [=](auto& mr) {
+        void *p = mr.allocate(Bytes, Align);
+        mr.deallocate(p, Bytes, Align);
+    };
+}
+
+int main()
+{
+    test_allocation_pattern(foo<2, 1>());
+    test_allocation_pattern(foo<2, 8>());
+    test_allocation_pattern(foo<2, 64>());
+    test_allocation_pattern(foo<128, 1>());
+    test_allocation_pattern(foo<128, 8>());
+    test_allocation_pattern(foo<128, 64>());
+    test_allocation_pattern(foo<1024, 1>());
+    test_allocation_pattern(foo<1024, 8>());
+    test_allocation_pattern(foo<1024, 64>());
+
+    test_allocation_pattern([](auto& mr) {
+        void *p1 = mr.allocate(2, 1);
+        void *p2 = mr.allocate(2, 8);
+        void *p3 = mr.allocate(2, 64);
+        void *p4 = mr.allocate(128, 1);
+        void *p5 = mr.allocate(128, 8);
+        void *p6 = mr.allocate(128, 64);
+        void *p7 = mr.allocate(1024, 1);
+        void *p8 = mr.allocate(1024, 8);
+        void *p9 = mr.allocate(1024, 64);
+        mr.deallocate(p1, 2, 1);
+        mr.deallocate(p2, 2, 8);
+        mr.deallocate(p3, 2, 64);
+        mr.deallocate(p4, 128, 1);
+        mr.deallocate(p5, 128, 8);
+        mr.deallocate(p6, 128, 64);
+        mr.deallocate(p7, 1024, 1);
+        mr.deallocate(p8, 1024, 8);
+        mr.deallocate(p9, 1024, 64);
+    });
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class unsynchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+int main()
+{
+    {
+        globalMemCounter.reset();
+
+        std::pmr::unsynchronized_pool_resource unsync1(std::pmr::new_delete_resource());
+        std::pmr::memory_resource & r1 = unsync1;
+
+        void *ret = r1.allocate(50);
+        assert(ret);
+        assert(globalMemCounter.checkNewCalledGreaterThan(0));
+        assert(globalMemCounter.checkDeleteCalledEq(0));
+
+        r1.deallocate(ret, 50);
+        unsync1.release();
+        assert(globalMemCounter.checkDeleteCalledGreaterThan(0));
+        assert(globalMemCounter.checkOutstandingNewEq(0));
+
+        globalMemCounter.reset();
+
+        ret = r1.allocate(500);
+        assert(ret);
+        assert(globalMemCounter.checkNewCalledGreaterThan(0));
+        assert(globalMemCounter.checkDeleteCalledEq(0));
+
+        // Check that the destructor calls release()
+    }
+    assert(globalMemCounter.checkDeleteCalledGreaterThan(0));
+    assert(globalMemCounter.checkOutstandingNewEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class unsynchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+bool is_aligned_to(void *p, size_t alignment)
+{
+    void *p2 = p;
+    size_t space = 1;
+    void *result = std::align(alignment, 1, p2, space);
+    return (result == p);
+}
+
+int main()
+{
+#ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
+
+    globalMemCounter.reset();
+    std::pmr::pool_options opts { 1, 1024 };
+    std::pmr::unsynchronized_pool_resource unsync1(opts, std::pmr::new_delete_resource());
+    std::pmr::memory_resource & r1 = unsync1;
+
+    constexpr size_t big_alignment = 8 * alignof(std::max_align_t);
+    static_assert(big_alignment > 4);
+
+    assert(globalMemCounter.checkNewCalledEq(0));
+
+    void *ret = r1.allocate(2048, big_alignment);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, big_alignment));
+    assert(globalMemCounter.checkNewCalledGreaterThan(0));
+
+    ret = r1.allocate(16, 4);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, 4));
+    assert(globalMemCounter.checkNewCalledGreaterThan(1));
+
+#endif
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_reuse_blocks.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_reuse_blocks.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class unsynchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+
+#include "count_new.h"
+
+static bool is_aligned_to(void *p, size_t alignment)
+{
+    void *p2 = p;
+    size_t space = 1;
+    void *result = std::align(alignment, 1, p2, space);
+    return (result == p);
+}
+
+int main()
+{
+    globalMemCounter.reset();
+    std::pmr::pool_options opts { 1, 256 };
+    std::pmr::unsynchronized_pool_resource unsync1(opts, std::pmr::new_delete_resource());
+    std::pmr::memory_resource & r1 = unsync1;
+
+    void *ret = r1.allocate(8);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, 8));
+    assert(globalMemCounter.checkNewCalledGreaterThan(0));
+    int new_called = globalMemCounter.new_called;
+
+    // After deallocation, the pool for 8-byte blocks should have at least one vacancy.
+    r1.deallocate(ret, 8);
+    assert(globalMemCounter.new_called == new_called);
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+
+    // This should return an existing block from the pool: no new allocations.
+    ret = r1.allocate(8);
+    assert(ret != nullptr);
+    assert(is_aligned_to(ret, 8));
+    assert(globalMemCounter.new_called == new_called);
+    assert(globalMemCounter.checkDeleteCalledEq(0));
+}
Index: test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// class unsynchronized_pool_resource
+
+#include <memory_resource>
+#include <cassert>
+#include <vector>
+
+struct allocation_record {
+    size_t bytes;
+    size_t align;
+    explicit allocation_record(size_t b, size_t a) : bytes(b), align(a) {}
+    bool operator==(const allocation_record& rhs) const {
+        return (bytes == rhs.bytes) && (align == rhs.align);
+    }
+    bool operator<(const allocation_record& rhs) const {
+        if (bytes != rhs.bytes) return (bytes < rhs.bytes);
+        return (align < rhs.align);
+    }
+};
+
+class test_resource : public std::pmr::memory_resource {
+    void *do_allocate(size_t bytes, size_t align) override {
+        void *result = std::pmr::new_delete_resource()->allocate(bytes, align);
+        successful_allocations.emplace_back(bytes, align);
+        return result;
+    }
+    void do_deallocate(void *p, size_t bytes, size_t align) override {
+        deallocations.emplace_back(bytes, align);
+        return std::pmr::new_delete_resource()->deallocate(p, bytes, align);
+    }
+    bool do_is_equal(const std::pmr::memory_resource&) const noexcept override {
+        return false;
+    }
+public:
+    std::vector<allocation_record> successful_allocations;
+    std::vector<allocation_record> deallocations;
+};
+
+template<class F>
+void test_allocation_pattern(F do_pattern)
+{
+    test_resource tr;
+    std::pmr::pool_options opts { 0, 256 };
+    std::pmr::unsynchronized_pool_resource uspr(opts, &tr);
+
+    try {
+        do_pattern(uspr);
+    } catch (const std::bad_alloc&) {}
+    uspr.release();
+
+    assert(tr.successful_allocations.size() == tr.deallocations.size());
+    std::sort(tr.successful_allocations.begin(), tr.successful_allocations.end());
+    std::sort(tr.deallocations.begin(), tr.deallocations.end());
+    assert(tr.successful_allocations == tr.deallocations);
+}
+
+template<size_t Bytes, size_t Align>
+auto foo() {
+    return [=](auto& mr) {
+        void *p = mr.allocate(Bytes, Align);
+        mr.deallocate(p, Bytes, Align);
+    };
+}
+
+int main()
+{
+    test_allocation_pattern(foo<2, 1>());
+    test_allocation_pattern(foo<2, 8>());
+    test_allocation_pattern(foo<2, 64>());
+    test_allocation_pattern(foo<128, 1>());
+    test_allocation_pattern(foo<128, 8>());
+    test_allocation_pattern(foo<128, 64>());
+    test_allocation_pattern(foo<1024, 1>());
+    test_allocation_pattern(foo<1024, 8>());
+    test_allocation_pattern(foo<1024, 64>());
+
+    test_allocation_pattern([](auto& mr) {
+        void *p1 = mr.allocate(2, 1);
+        void *p2 = mr.allocate(2, 8);
+        void *p3 = mr.allocate(2, 64);
+        void *p4 = mr.allocate(128, 1);
+        void *p5 = mr.allocate(128, 8);
+        void *p6 = mr.allocate(128, 64);
+        void *p7 = mr.allocate(1024, 1);
+        void *p8 = mr.allocate(1024, 8);
+        void *p9 = mr.allocate(1024, 64);
+        mr.deallocate(p1, 2, 1);
+        mr.deallocate(p2, 2, 8);
+        mr.deallocate(p3, 2, 64);
+        mr.deallocate(p4, 128, 1);
+        mr.deallocate(p5, 128, 8);
+        mr.deallocate(p6, 128, 64);
+        mr.deallocate(p7, 1024, 1);
+        mr.deallocate(p8, 1024, 8);
+        mr.deallocate(p9, 1024, 64);
+    });
+}
Index: test/std/utilities/utility/mem.res/mem.res/construct.fail.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/construct.fail.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// Check that memory_resource is not constructible
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+namespace ex = std::pmr;
+
+int main()
+{
+    ex::memory_resource m; // expected-error {{variable type 'ex::memory_resource' is an abstract class}}
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.eq/equal.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.eq/equal.pass.cpp
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// bool operator==(memory_resource const &, memory_resource const &) noexcept;
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+int main()
+{
+    // check return types
+    {
+        ex::memory_resource const * mr1(nullptr);
+        ex::memory_resource const * mr2(nullptr);
+        static_assert(std::is_same<decltype(*mr1 == *mr2), bool>::value, "");
+        static_assert(noexcept(*mr1 == *mr2), "");
+    }
+    // equal
+    {
+        TestResource r1(1);
+        TestResource r2(1);
+        ex::memory_resource const & mr1 = r1;
+        ex::memory_resource const & mr2 = r2;
+
+        assert(mr1 == mr2);
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(0));
+
+        assert(mr2 == mr1);
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(1));
+    }
+    // equal same object
+    {
+        TestResource r1(1);
+        ex::memory_resource const & mr1 = r1;
+        ex::memory_resource const & mr2 = r1;
+
+        assert(mr1 == mr2);
+        assert(r1.checkIsEqualCalledEq(0));
+
+        assert(mr2 == mr1);
+        assert(r1.checkIsEqualCalledEq(0));
+    }
+    // not equal
+    {
+        TestResource r1(1);
+        TestResource r2(2);
+        ex::memory_resource const & mr1 = r1;
+        ex::memory_resource const & mr2 = r2;
+
+        assert(!(mr1 == mr2));
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(0));
+
+        assert(!(mr2 == mr1));
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(1));
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.eq/not_equal.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.eq/not_equal.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// bool operator!=(memory_resource const &, memory_resource const &) noexcept;
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+namespace ex = std::pmr;
+
+int main()
+{
+    // check return types
+    {
+        ex::memory_resource const * mr1(nullptr);
+        ex::memory_resource const * mr2(nullptr);
+        static_assert(std::is_same<decltype(*mr1 != *mr2), bool>::value, "");
+        static_assert(noexcept(*mr1 != *mr2), "");
+    }
+    // not equal
+    {
+        TestResource r1(1);
+        TestResource r2(2);
+        ex::memory_resource const & mr1 = r1;
+        ex::memory_resource const & mr2 = r2;
+
+        assert(mr1 != mr2);
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(0));
+
+        assert(mr2 != mr1);
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(1));
+    }
+    // equal
+    {
+        TestResource r1(1);
+        TestResource r2(1);
+        ex::memory_resource const & mr1 = r1;
+        ex::memory_resource const & mr2 = r2;
+
+        assert(!(mr1 != mr2));
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(0));
+
+        assert(!(mr2 != mr1));
+        assert(r1.checkIsEqualCalledEq(1));
+        assert(r2.checkIsEqualCalledEq(1));
+    }
+    // equal same object
+    {
+        TestResource r1(1);
+        ex::memory_resource const & mr1 = r1;
+        ex::memory_resource const & mr2 = r1;
+
+        assert(!(mr1 != mr2));
+        assert(r1.checkIsEqualCalledEq(0));
+
+        assert(!(mr2 != mr1));
+        assert(r1.checkIsEqualCalledEq(0));
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.private/private_members.fail.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.private/private_members.fail.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// memory_resource::do_allocate(size_t, size_t);          /* private */
+// memory_resource::do_deallocate(void*, size_t, size_t); /* private */
+// memory_resource::do_is_equal(memory_resource const&);  /* private */
+
+#include <memory_resource>
+
+namespace ex = std::pmr;
+
+int main() {
+    ex::memory_resource *m = ex::new_delete_resource();
+    m->do_allocate(0, 0); // expected-error{{'do_allocate' is a private member}}
+    m->do_deallocate(nullptr, 0, 0); // expected-error{{'do_deallocate' is a private member}}
+    m->do_is_equal(*m); // expected-error{{'do_is_equal' is a private member}}
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.private/protected_members.fail.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.private/protected_members.fail.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+// monotonic_buffer_resource::do_allocate(size_t, size_t);          /* protected */
+// monotonic_buffer_resource::do_deallocate(void*, size_t, size_t); /* protected */
+// monotonic_buffer_resource::do_is_equal(memory_resource const&);  /* protected */
+
+// synchronized_pool_resource::do_allocate(size_t, size_t);          /* protected */
+// synchronized_pool_resource::do_deallocate(void*, size_t, size_t); /* protected */
+// synchronized_pool_resource::do_is_equal(memory_resource const&);  /* protected */
+
+// unsynchronized_pool_resource::do_allocate(size_t, size_t);          /* protected */
+// unsynchronized_pool_resource::do_deallocate(void*, size_t, size_t); /* protected */
+// unsynchronized_pool_resource::do_is_equal(memory_resource const&);  /* protected */
+
+#include <memory_resource>
+
+int main() {
+    {
+        std::pmr::monotonic_buffer_resource m;
+        m.do_allocate(0, 0); // expected-error{{'do_allocate' is a protected member}}
+        m.do_deallocate(nullptr, 0, 0); // expected-error{{'do_deallocate' is a protected member}}
+        m.do_is_equal(m); // expected-error{{'do_is_equal' is a protected member}}
+    }
+    {
+        std::pmr::synchronized_pool_resource m;
+        m.do_allocate(0, 0); // expected-error{{'do_allocate' is a protected member}}
+        m.do_deallocate(nullptr, 0, 0); // expected-error{{'do_deallocate' is a protected member}}
+        m.do_is_equal(m); // expected-error{{'do_is_equal' is a protected member}}
+    }
+    {
+        std::pmr::unsynchronized_pool_resource m;
+        m.do_allocate(0, 0); // expected-error{{'do_allocate' is a protected member}}
+        m.do_deallocate(nullptr, 0, 0); // expected-error{{'do_deallocate' is a protected member}}
+        m.do_is_equal(m); // expected-error{{'do_is_equal' is a protected member}}
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.public/allocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.public/allocate.pass.cpp
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <memory_resource>
+
+// UNSUPPORTED: c++98, c++03
+
+//------------------------------------------------------------------------------
+// TESTING void * memory_resource::allocate(size_t, size_t = max_align)
+//
+// Concerns:
+//  A) 'memory_resource' contains a member 'allocate' with the required
+//     signature, including the default alignment parameter.
+//  B) The return type of 'allocate' is 'void*'.
+//  C) 'allocate' is not marked as 'noexcept'.
+//  D) Invoking 'allocate' invokes 'do_allocate' with the same arguments.
+//  E) If 'do_allocate' throws then 'allocate' propagates that exception.
+
+#include <memory_resource>
+#include <type_traits>
+#include <cstddef>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_std_memory_resource.h"
+
+using std::pmr::memory_resource;
+
+int main()
+{
+    TestResource R(42);
+    auto& P = R.getController();
+    memory_resource& M = R;
+    {
+        static_assert(
+            std::is_same<decltype(M.allocate(0, 0)), void*>::value
+          , "Must be void*"
+          );
+        static_assert(
+            std::is_same<decltype(M.allocate(0)), void*>::value
+          , "Must be void*"
+          );
+    }
+    {
+        static_assert(
+            ! noexcept(M.allocate(0, 0))
+          , "Must not be noexcept."
+          );
+        static_assert(
+            ! noexcept(M.allocate(0))
+          , "Must not be noexcept."
+          );
+    }
+    {
+        int s = 42;
+        int a = 64;
+        void* p = M.allocate(s, a);
+        assert(P.alloc_count == 1);
+        assert(P.checkAlloc(p, s, a));
+
+        s = 128;
+        a = MaxAlignV;
+        p = M.allocate(s);
+        assert(P.alloc_count == 2);
+        assert(P.checkAlloc(p, s, a));
+    }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+    {
+        TestResource R2;
+        auto& P2 = R2.getController();
+        P2.throw_on_alloc = true;
+        memory_resource& M2 = R2;
+        try {
+            M2.allocate(42);
+            assert(false);
+        } catch (TestException const&) {
+            // do nothing.
+        } catch (...) {
+            assert(false);
+        }
+    }
+#endif
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.public/deallocate.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.public/deallocate.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <memory_resource>
+
+// UNSUPPORTED: c++98, c++03
+
+//------------------------------------------------------------------------------
+// TESTING void * memory_resource::deallocate(void *, size_t, size_t = max_align)
+//
+// Concerns:
+//  A) 'memory_resource' contains a member 'deallocate' with the required
+//     signature, including the default alignment parameter.
+//  B) The return type of 'deallocate' is 'void'.
+//  C) 'deallocate' is not marked as 'noexcept'.
+//  D) Invoking 'deallocate' invokes 'do_deallocate' with the same arguments.
+
+
+#include <memory_resource>
+#include <type_traits>
+#include <cstddef>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+using std::pmr::memory_resource;
+
+int main()
+{
+    NullResource R(42);
+    auto& P = R.getController();
+    memory_resource& M = R;
+    {
+        static_assert(
+            std::is_same<decltype(M.deallocate(nullptr, 0, 0)), void>::value
+          , "Must be void"
+          );
+        static_assert(
+            std::is_same<decltype(M.deallocate(nullptr, 0)), void>::value
+          , "Must be void"
+          );
+    }
+    {
+        static_assert(
+            ! noexcept(M.deallocate(nullptr, 0, 0))
+          , "Must not be noexcept."
+          );
+        static_assert(
+            ! noexcept(M.deallocate(nullptr, 0))
+          , "Must not be noexcept."
+          );
+    }
+    {
+        int s = 100;
+        int a = 64;
+        void* p = reinterpret_cast<void*>(640);
+        M.deallocate(p, s, a);
+        assert(P.dealloc_count == 1);
+        assert(P.checkDealloc(p, s, a));
+
+        s = 128;
+        a = alignof(std::max_align_t);
+        p = reinterpret_cast<void*>(12800);
+        M.deallocate(p, s);
+        assert(P.dealloc_count == 2);
+        assert(P.checkDealloc(p, s, a));
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.public/dtor.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.public/dtor.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+//------------------------------------------------------------------------------
+// TESTING virtual ~memory_resource()
+//
+// Concerns:
+//  A) 'memory_resource' is destructible.
+//  B) The destructor is implicitly marked noexcept.
+//  C) The destructor is marked virtual.
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#include "test_std_memory_resource.h"
+
+using std::pmr::memory_resource;
+
+int main()
+{
+    static_assert(
+        std::has_virtual_destructor<memory_resource>::value
+      , "Must have virtual destructor"
+      );
+    static_assert(
+        std::is_nothrow_destructible<memory_resource>::value,
+        "Must be nothrow destructible"
+      );
+    static_assert(
+        std::is_abstract<memory_resource>::value
+      , "Must be abstract"
+      );
+    // Check that the destructor of `TestResource` is called when
+    // it is deleted as a pointer to `memory_resource`
+    {
+        using TR = TestResource;
+        memory_resource* M = new TR(42);
+        assert(TR::resource_alive == 1);
+        assert(TR::resource_constructed == 1);
+        assert(TR::resource_destructed == 0);
+
+        delete M;
+
+        assert(TR::resource_alive == 0);
+        assert(TR::resource_constructed == 1);
+        assert(TR::resource_destructed == 1);
+    }
+}
Index: test/std/utilities/utility/mem.res/mem.res/mem.res.public/is_equal.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/utility/mem.res/mem.res/mem.res.public/is_equal.pass.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory_resource>
+
+//------------------------------------------------------------------------------
+// TESTING virtual bool is_equal(memory_resource const &) const noexcept
+//
+// Concerns:
+//   A) 'memory_resource' provides a function 'is_equal' with the required
+//      signature.
+//   B) 'is_equal' is noexcept.
+//   C) 'do_is_equal' is called using the same arguments passed to 'is_equal'
+//      and the resulting value is returned.
+//   D) 'do_is_equal' is called on the LHS object and not the RHS object.
+
+#include <memory_resource>
+#include <type_traits>
+#include <cassert>
+#include "test_std_memory_resource.h"
+
+using std::pmr::memory_resource;
+
+int main()
+{
+    {
+        memory_resource const* r1 = nullptr;
+        memory_resource const* r2 = nullptr;
+        static_assert(
+            noexcept(r1->is_equal(*r2))
+          , "is_equal must be noexcept"
+          );
+    }
+    {
+        TestResource1 R1(1);
+        auto& P1 = R1.getController();
+        memory_resource const& M1 = R1;
+
+        TestResource2 R2(1);
+        auto& P2 = R2.getController();
+        memory_resource const& M2 = R2;
+
+        assert(M1.is_equal(M2) == false);
+        assert(P1.checkIsEqualCalledEq(1));
+        assert(P2.checkIsEqualCalledEq(0));
+
+        assert(M2.is_equal(M1) == false);
+        assert(P2.checkIsEqualCalledEq(1));
+        assert(P1.checkIsEqualCalledEq(1));
+    }
+    {
+        TestResource1 R1(1);
+        auto& P1 = R1.getController();
+        memory_resource const& M1 = R1;
+
+        TestResource1 R2(2);
+        auto& P2 = R2.getController();
+        memory_resource const& M2 = R2;
+
+        assert(M1.is_equal(M2) == false);
+        assert(P1.checkIsEqualCalledEq(1));
+        assert(P2.checkIsEqualCalledEq(0));
+
+        assert(M2.is_equal(M1) == false);
+        assert(P2.checkIsEqualCalledEq(1));
+        assert(P1.checkIsEqualCalledEq(1));
+    }
+    {
+        TestResource1 R1(1);
+        auto& P1 = R1.getController();
+        memory_resource const& M1 = R1;
+
+        TestResource1 R2(1);
+        auto& P2 = R2.getController();
+        memory_resource const& M2 = R2;
+
+        assert(M1.is_equal(M2) == true);
+        assert(P1.checkIsEqualCalledEq(1));
+        assert(P2.checkIsEqualCalledEq(0));
+
+        assert(M2.is_equal(M1) == true);
+        assert(P2.checkIsEqualCalledEq(1));
+        assert(P1.checkIsEqualCalledEq(1));
+    }
+}
Index: test/support/test_std_memory_resource.h
===================================================================
--- /dev/null
+++ test/support/test_std_memory_resource.h
@@ -0,0 +1,162 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUPPORT_TEST_STD_MEMORY_RESOURCE_H
+#define SUPPORT_TEST_STD_MEMORY_RESOURCE_H
+
+#include <memory>
+#include <memory_resource>
+#include <type_traits>
+#include <utility>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <cstdint>
+#include <cassert>
+#include "test_macros.h"
+#include "controlled_allocators.h"
+#include "uses_alloc_types.h"
+
+template <class ProviderT, int = 0>
+class TestResourceImp : public std::pmr::memory_resource
+{
+public:
+    static int resource_alive;
+    static int resource_constructed;
+    static int resource_destructed;
+
+    static void resetStatics() {
+        assert(resource_alive == 0);
+        resource_alive = 0;
+        resource_constructed = 0;
+        resource_destructed = 0;
+    }
+
+    using memory_resource = std::pmr::memory_resource;
+    using Provider = ProviderT;
+
+    int value;
+
+    explicit TestResourceImp(int val = 0) : value(val) {
+        ++resource_alive;
+        ++resource_constructed;
+    }
+
+    ~TestResourceImp() noexcept {
+        --resource_alive;
+        ++resource_destructed;
+    }
+
+    void reset() { C.reset(); P.reset(); }
+    AllocController& getController() { return C; }
+
+    bool checkAlloc(void* p, std::size_t s, std::size_t a) const
+      { return C.checkAlloc(p, s, a); }
+
+    bool checkDealloc(void* p, std::size_t s, std::size_t a) const
+      { return C.checkDealloc(p, s, a); }
+
+    bool checkIsEqualCalledEq(int n) const { return C.checkIsEqualCalledEq(n); }
+
+protected:
+    virtual void * do_allocate(std::size_t s, std::size_t a) {
+        if (C.throw_on_alloc) {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+            throw TestException{};
+#else
+            assert(false);
+#endif
+        }
+        void* ret = P.allocate(s, a);
+        C.countAlloc(ret, s, a);
+        return ret;
+    }
+
+    virtual void do_deallocate(void * p, std::size_t s, std::size_t a) {
+        C.countDealloc(p, s, a);
+        P.deallocate(p, s, a);
+    }
+
+    virtual bool do_is_equal(memory_resource const & other) const noexcept {
+        C.countIsEqual();
+        TestResourceImp const * o = dynamic_cast<TestResourceImp const *>(&other);
+        return o && o->value == value;
+    }
+private:
+    mutable AllocController C;
+    mutable Provider P;
+    DISALLOW_COPY(TestResourceImp);
+};
+
+template <class Provider, int N>
+int TestResourceImp<Provider, N>::resource_alive = 0;
+
+template <class Provider, int N>
+int TestResourceImp<Provider, N>::resource_constructed = 0;
+
+template <class Provider, int N>
+int TestResourceImp<Provider, N>::resource_destructed = 0;
+
+
+struct NullProvider {
+    NullProvider() {}
+    void* allocate(size_t, size_t) { return nullptr; }
+    void deallocate(void*, size_t, size_t) {}
+    void reset() {}
+private:
+    DISALLOW_COPY(NullProvider);
+};
+
+struct NewDeleteProvider {
+    NewDeleteProvider() {}
+    void* allocate(size_t s, size_t) { return ::operator new(s); }
+    void deallocate(void* p, size_t, size_t) { ::operator delete(p); }
+    void reset() {}
+private:
+    DISALLOW_COPY(NewDeleteProvider);
+};
+
+template <size_t Size = 4096 * 10> // 10 pages worth of memory.
+struct BufferProvider {
+    char buffer[Size];
+    void* next = &buffer;
+    size_t space = Size;
+
+    BufferProvider() {}
+
+    void* allocate(size_t s, size_t a) {
+        void* ret = std::align(s, a, next, space);
+        if (ret == nullptr) {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+            throw std::bad_alloc();
+#else
+            assert(false);
+#endif
+        }
+
+        return ret;
+    }
+
+    void deallocate(void*, size_t, size_t) {}
+
+    void reset() {
+        next = &buffer;
+        space = Size;
+    }
+private:
+    DISALLOW_COPY(BufferProvider);
+};
+
+using NullResource = TestResourceImp<NullProvider, 0>;
+using NewDeleteResource = TestResourceImp<NewDeleteProvider, 0>;
+using TestResource  = TestResourceImp<BufferProvider<>, 0>;
+using TestResource1 = TestResourceImp<BufferProvider<>, 1>;
+using TestResource2 = TestResourceImp<BufferProvider<>, 2>;
+
+
+#endif /* SUPPORT_TEST_STD_MEMORY_RESOURCE_H */
Index: utils/generate_feature_test_macro_components.py
===================================================================
--- utils/generate_feature_test_macro_components.py
+++ utils/generate_feature_test_macro_components.py
@@ -285,7 +285,6 @@
      "c++17": 201603L,
    },
    "headers": ["memory_resource"],
-   "unimplemented": True,
    },
   {"name": "__cpp_lib_boyer_moore_searcher",
    "values": {