[libcxx-commits] [libcxx] 7a62bee - [libc++] Implement std::experimental::observer_ptr
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Nov 5 17:01:45 PST 2023
Author: Zoe Carver
Date: 2023-11-05T17:59:04-07:00
New Revision: 7a62bee611f1c451fa026c146b03a3a277a5a1dd
URL: https://github.com/llvm/llvm-project/commit/7a62bee611f1c451fa026c146b03a3a277a5a1dd
DIFF: https://github.com/llvm/llvm-project/commit/7a62bee611f1c451fa026c146b03a3a277a5a1dd.diff
LOG: [libc++] Implement std::experimental::observer_ptr
This patch adds std::experimental::observer_ptr (n4282) and also
fixes LWG2516.
Co-Authored-By: Louis Dionne <ldionne.2 at gmail.com>
Differential Revision: https://reviews.llvm.org/D63230
Added:
libcxx/include/experimental/memory
libcxx/test/std/experimental/memory/memory.observer.ptr/compare.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.convert.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.copy_move.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.default.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.element_type.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.nullptr.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/deref.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/get.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/hash.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/make_observer.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/operator-bool.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/operator-element_type.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/release.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/reset.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/swap.pass.cpp
libcxx/test/std/experimental/memory/memory.observer.ptr/types.compile.pass.cpp
Modified:
libcxx/docs/Status/Cxx17Issues.csv
libcxx/include/CMakeLists.txt
libcxx/include/__std_clang_module
libcxx/include/module.modulemap.in
libcxx/test/libcxx/transitive_includes/cxx03.csv
libcxx/test/libcxx/transitive_includes/cxx11.csv
libcxx/test/libcxx/transitive_includes/cxx14.csv
libcxx/test/libcxx/transitive_includes/cxx17.csv
libcxx/test/libcxx/transitive_includes/cxx20.csv
libcxx/test/libcxx/transitive_includes/cxx23.csv
libcxx/test/libcxx/transitive_includes/cxx26.csv
Removed:
################################################################################
diff --git a/libcxx/docs/Status/Cxx17Issues.csv b/libcxx/docs/Status/Cxx17Issues.csv
index bc231c8e8a1b42f..ebe59ddc89fa881 100644
--- a/libcxx/docs/Status/Cxx17Issues.csv
+++ b/libcxx/docs/Status/Cxx17Issues.csv
@@ -143,7 +143,7 @@
"`2441 <https://wg21.link/LWG2441>`__","Exact-width atomic typedefs should be provided","Oulu","|Complete|",""
"`2451 <https://wg21.link/LWG2451>`__","[fund.ts.v2] optional should 'forward' T's implicit conversions","Oulu","|Nothing To Do|",""
"`2509 <https://wg21.link/LWG2509>`__","[fund.ts.v2] any_cast doesn't work with rvalue reference targets and cannot move with a value target","Oulu","|Complete|",""
-"`2516 <https://wg21.link/LWG2516>`__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","Oulu","",""
+"`2516 <https://wg21.link/LWG2516>`__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","Oulu","|Complete|","18.0"
"`2542 <https://wg21.link/LWG2542>`__","Missing const requirements for associative containers","Oulu","",""
"`2549 <https://wg21.link/LWG2549>`__","Tuple EXPLICIT constructor templates that take tuple parameters end up taking references to temporaries and will create dangling references","Oulu","|Complete|",""
"`2550 <https://wg21.link/LWG2550>`__","Wording of unordered container's clear() method complexity","Oulu","|Complete|",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index b7b14200498a298..5e8c1700ee4cdad 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -925,6 +925,7 @@ set(files
experimental/iterator
experimental/list
experimental/map
+ experimental/memory
experimental/memory_resource
experimental/propagate_const
experimental/regex
diff --git a/libcxx/include/__std_clang_module b/libcxx/include/__std_clang_module
index e2e9e85ffc7d8d6..c4bfe8259c74a3a 100644
--- a/libcxx/include/__std_clang_module
+++ b/libcxx/include/__std_clang_module
@@ -91,6 +91,7 @@
#include <experimental/iterator>
#include <experimental/list>
#include <experimental/map>
+#include <experimental/memory>
#include <experimental/memory_resource>
#include <experimental/propagate_const>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
diff --git a/libcxx/include/experimental/memory b/libcxx/include/experimental/memory
new file mode 100644
index 000000000000000..9de57072759c70d
--- /dev/null
+++ b/libcxx/include/experimental/memory
@@ -0,0 +1,194 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP_EXPERIMENTAL_MEMORY
+#define _LIBCPP_EXPERIMENTAL_MEMORY
+
+/*
+ experimental/memory synopsis
+
+namespace std::experimental::inline fundamentals_v2 {
+
+template <class W> class observer_ptr {
+public:
+ using element_type = W;
+ using pointer = add_pointer_t<W>; // exposition-only
+ using reference = add_lvalue_reference_t<W>; // exposition-only
+
+ // default ctor
+ constexpr observer_ptr() noexcept;
+
+ // pointer-accepting ctors
+ constexpr observer_ptr(nullptr_t) noexcept;
+ constexpr explicit observer_ptr(pointer) noexcept;
+
+ // copying ctors (in addition to compiler-generated copy ctor)
+ template <class W2> constexpr observer_ptr(observer_ptr<W2>) noexcept;
+
+ // observers
+ constexpr pointer get() const noexcept;
+ constexpr reference operator*() const;
+ constexpr pointer operator->() const noexcept;
+ constexpr explicit operator bool() const noexcept;
+
+ // conversions
+ constexpr explicit operator pointer() const noexcept;
+
+ // modifiers
+ constexpr pointer release() noexcept;
+ constexpr void reset(pointer = nullptr) noexcept;
+ constexpr void swap(observer_ptr&) noexcept;
+};
+
+}
+*/
+
+#include <__functional/hash.h>
+#include <__functional/operations.h>
+#include <__type_traits/add_lvalue_reference.h>
+#include <__type_traits/add_pointer.h>
+#include <__type_traits/common_type.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_convertible.h>
+#include <cstddef>
+#include <experimental/__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#ifdef _LIBCPP_ENABLE_EXPERIMENTAL
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS_V2
+
+# if _LIBCPP_STD_VER >= 17
+
+template <class _Wp>
+class observer_ptr {
+public:
+ using element_type = _Wp;
+
+ // constructors
+ _LIBCPP_HIDE_FROM_ABI constexpr observer_ptr() noexcept : __ptr_(nullptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr observer_ptr(nullptr_t) noexcept : __ptr_(nullptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit observer_ptr(element_type* __p) noexcept : __ptr_(__p) {}
+
+ template <class _W2, class = __enable_if_t<is_convertible<_W2*, _Wp*>::value>>
+ _LIBCPP_HIDE_FROM_ABI constexpr observer_ptr(observer_ptr<_W2> __other) noexcept : __ptr_(__other.get()) {}
+
+ // observers
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* get() const noexcept { return __ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr add_lvalue_reference_t<_Wp> operator*() const { return *__ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* operator->() const noexcept { return __ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __ptr_ != nullptr; }
+
+ // conversions
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit operator element_type*() const noexcept { return __ptr_; }
+
+ // modifiers
+ _LIBCPP_HIDE_FROM_ABI constexpr void reset(element_type* __p = nullptr) noexcept { __ptr_ = __p; }
+ _LIBCPP_HIDE_FROM_ABI constexpr void swap(observer_ptr& __other) noexcept {
+ observer_ptr __tmp = __other;
+ __other = *this;
+ *this = __tmp;
+ }
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* release() noexcept {
+ observer_ptr __p;
+ __p.swap(*this);
+ return __p.get();
+ }
+
+private:
+ element_type* __ptr_;
+};
+
+// specializations
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI constexpr void swap(observer_ptr<_Wp>& __a, observer_ptr<_Wp>& __b) noexcept {
+ __a.swap(__b);
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI observer_ptr<_Wp> make_observer(_Wp* __ptr) noexcept {
+ return observer_ptr<_Wp>{__ptr};
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return __a.get() == __b.get();
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return !(__a == __b);
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_Wp> __p, nullptr_t) {
+ return !__p;
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, observer_ptr<_Wp> __p) {
+ return !__p;
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_Wp> __p, nullptr_t) {
+ return (bool)__p;
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, observer_ptr<_Wp> __p) {
+ return (bool)__p;
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator<(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return std::less<typename std::common_type<_W1*, _W2*>::type>()(__a.get(), __b.get());
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator>(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return __b < __a;
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator<=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return !(__a > __b);
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator>=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return !(__a < __b);
+}
+
+# endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_LFTS_V2
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// hash
+
+# if _LIBCPP_STD_VER >= 17
+template <class _Tp>
+struct hash<experimental::observer_ptr<_Tp>> {
+ _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::observer_ptr<_Tp>& __ptr) const noexcept {
+ return hash<_Tp*>()(__ptr.get());
+ }
+};
+# endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_ENABLE_EXPERIMENTAL
+
+#endif /* _LIBCPP_EXPERIMENTAL_MEMORY */
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index f447b2fa0a0ce94..17ebe48f329963d 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -533,6 +533,10 @@ module std_experimental [system] {
header "experimental/map"
export *
}
+ module memory {
+ header "experimental/memory"
+ export *
+ }
module memory_resource {
header "experimental/memory_resource"
export *
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index e41a3b290cf6ef5..0e7523b5420d43d 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -241,6 +241,10 @@ experimental/list experimental/memory_resource
experimental/list list
experimental/map experimental/memory_resource
experimental/map map
+experimental/memory cstddef
+experimental/memory cstdint
+experimental/memory cstring
+experimental/memory limits
experimental/memory_resource atomic
experimental/memory_resource climits
experimental/memory_resource concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 4ac3dccc50040f8..08e7786d9b19435 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -242,6 +242,10 @@ experimental/list experimental/memory_resource
experimental/list list
experimental/map experimental/memory_resource
experimental/map map
+experimental/memory cstddef
+experimental/memory cstdint
+experimental/memory cstring
+experimental/memory limits
experimental/memory_resource atomic
experimental/memory_resource climits
experimental/memory_resource concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 4f3fdfdd4d2cae5..37a6e5e853d27e7 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -242,6 +242,10 @@ experimental/list experimental/memory_resource
experimental/list list
experimental/map experimental/memory_resource
experimental/map map
+experimental/memory cstddef
+experimental/memory cstdint
+experimental/memory cstring
+experimental/memory limits
experimental/memory_resource atomic
experimental/memory_resource climits
experimental/memory_resource concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 4f3fdfdd4d2cae5..37a6e5e853d27e7 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -242,6 +242,10 @@ experimental/list experimental/memory_resource
experimental/list list
experimental/map experimental/memory_resource
experimental/map map
+experimental/memory cstddef
+experimental/memory cstdint
+experimental/memory cstring
+experimental/memory limits
experimental/memory_resource atomic
experimental/memory_resource climits
experimental/memory_resource concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 590a39e1b28e93f..5c9638fd467f214 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -248,6 +248,10 @@ experimental/list experimental/memory_resource
experimental/list list
experimental/map experimental/memory_resource
experimental/map map
+experimental/memory cstddef
+experimental/memory cstdint
+experimental/memory cstring
+experimental/memory limits
experimental/memory_resource atomic
experimental/memory_resource climits
experimental/memory_resource concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index aa6879026c90265..e1d489391c8de6c 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -170,6 +170,10 @@ experimental/list experimental/memory_resource
experimental/list list
experimental/map experimental/memory_resource
experimental/map map
+experimental/memory cstddef
+experimental/memory cstdint
+experimental/memory cstring
+experimental/memory limits
experimental/memory_resource cstddef
experimental/memory_resource experimental/utility
experimental/memory_resource limits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index aa6879026c90265..e1d489391c8de6c 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -170,6 +170,10 @@ experimental/list experimental/memory_resource
experimental/list list
experimental/map experimental/memory_resource
experimental/map map
+experimental/memory cstddef
+experimental/memory cstdint
+experimental/memory cstring
+experimental/memory limits
experimental/memory_resource cstddef
experimental/memory_resource experimental/utility
experimental/memory_resource limits
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/compare.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/compare.pass.cpp
new file mode 100644
index 000000000000000..c6f70f6a2b1d1b3
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/compare.pass.cpp
@@ -0,0 +1,179 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// template <class W1, class W2>
+// bool operator==(const observer_ptr<W1>& p1, const observer_ptr<W2>& p2);
+//
+// template <class W1, class W2>
+// bool operator!=(const observer_ptr<W1>& p1, const observer_ptr<W2>& p2);
+//
+// template <class W>
+// bool operator==(const observer_ptr<W>& p, std::nullptr_t) noexcept;
+//
+// template <class W>
+// bool operator==(std::nullptr_t, const observer_ptr<W>& p) noexcept;
+//
+// template <class W>
+// bool operator!=(const observer_ptr<W>& p, std::nullptr_t) noexcept;
+//
+// template <class W>
+// bool operator!=(std::nullptr_t, const observer_ptr<W>& p) noexcept;
+//
+// template <class W1, class W2>
+// bool operator<(const observer_ptr<W1>& p1, const observer_ptr<W2>& p2);
+//
+// template <class W1, class W2>
+// bool operator>(const observer_ptr<W1>& p1, const observer_ptr<W2>& p2);
+//
+// template <class W1, class W2>
+// bool operator<=(const observer_ptr<W1>& p1, const observer_ptr<W2>& p2);
+//
+// template <class W1, class W2>
+// bool operator>=(const observer_ptr<W1>& p1, const observer_ptr<W2>& p2);
+
+#include <experimental/memory>
+#include <cassert>
+
+void test() {
+ using T = int;
+ using Ptr = std::experimental::observer_ptr<T>;
+ using VoidPtr = std::experimental::observer_ptr<void>;
+
+ // operator==(observer_ptr, observer_ptr)
+ {
+ T obj1, obj2;
+ Ptr ptr1(&obj1), ptr1_x(&obj1);
+ Ptr ptr2(&obj2);
+ VoidPtr ptr3(&obj1);
+
+ assert(!(ptr1 == ptr2));
+ assert(ptr1 == ptr1_x);
+
+ assert(ptr1 == ptr3);
+ }
+
+ // operator!=(observer_ptr, observer_ptr)
+ {
+ T obj1, obj2;
+ Ptr ptr1(&obj1), ptr1_x(&obj1);
+ Ptr ptr2(&obj2);
+ VoidPtr ptr3(&obj1);
+
+ assert(ptr1 != ptr2);
+ assert(!(ptr1 != ptr1_x));
+
+ assert(ptr2 != ptr3);
+ }
+
+ // operator==(observer_ptr, nullptr_t)
+ {
+ T obj1;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(nullptr);
+
+ assert(!(ptr1 == nullptr));
+ assert(ptr2 == nullptr);
+ }
+
+ // operator==(nullptr_t, observer_ptr)
+ {
+ T obj1;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(nullptr);
+
+ assert(!(nullptr == ptr1));
+ assert(nullptr == ptr2);
+ }
+
+ // operator!=(observer_ptr, nullptr_t)
+ {
+ T obj1;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(nullptr);
+
+ assert(ptr1 != nullptr);
+ assert(!(ptr2 != nullptr));
+ }
+
+ // operator!=(nullptr_t, observer_ptr)
+ {
+ T obj1;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(nullptr);
+
+ assert(nullptr != ptr1);
+ assert(!(nullptr != ptr2));
+ }
+
+ // operator<(observer_ptr, observer_ptr)
+ {
+ T obj1, obj2;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(&obj2);
+ VoidPtr ptr3(&obj1);
+
+ assert(!(ptr1 < ptr1));
+ assert((ptr1 < ptr2) == (&obj1 < &obj2));
+
+ assert(!(ptr1 < ptr3));
+ }
+
+ // operator>(observer_ptr, observer_ptr)
+ {
+ T obj1, obj2;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(&obj2);
+ VoidPtr ptr3(&obj1);
+
+ assert(!(ptr1 > ptr1));
+ assert((ptr1 > ptr2) == (&obj1 > &obj2));
+
+ assert(!(ptr1 > ptr3));
+ }
+
+ // operator<=(observer_ptr, observer_ptr)
+ {
+ T obj1, obj2;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(&obj2);
+ VoidPtr ptr3(&obj1);
+
+ assert(ptr1 <= ptr1);
+ assert((ptr1 <= ptr2) == (&obj1 <= &obj2));
+
+ assert(ptr1 <= ptr3);
+ }
+
+ // operator>=(observer_ptr, observer_ptr)
+ {
+ T obj1, obj2;
+ Ptr ptr1(&obj1);
+ Ptr ptr2(&obj2);
+ VoidPtr ptr3(&obj1);
+
+ assert(ptr1 >= ptr1);
+ assert((ptr1 >= ptr2) == (&obj1 >= &obj2));
+
+ assert(ptr1 >= ptr3);
+ }
+}
+
+int main(int, char**) {
+ // Note: this is not constexpr in the spec
+ test();
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.convert.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.convert.pass.cpp
new file mode 100644
index 000000000000000..f0abba095569852
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.convert.pass.cpp
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// template <class W2>
+// constexpr observer_ptr(observer_ptr<W2> other) noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class To, class From>
+constexpr void test_converting_ctor() {
+ using ToPtr = std::experimental::observer_ptr<To>;
+ using FromPtr = std::experimental::observer_ptr<From>;
+ From obj;
+ FromPtr from(&obj);
+ ToPtr to = from;
+
+ assert(from.get() == &obj);
+ assert(to.get() == &obj);
+#if TEST_STD_VER >= 20
+ static_assert(std::is_nothrow_convertible<FromPtr, ToPtr>::value);
+#endif
+}
+
+template <class To, class From>
+constexpr void check_non_constructible() {
+ using ToPtr = std::experimental::observer_ptr<To>;
+ using FromPtr = std::experimental::observer_ptr<From>;
+ static_assert(!std::is_constructible<ToPtr, FromPtr>::value);
+}
+
+struct Bar {};
+struct Base {};
+struct Derived : Base {};
+
+constexpr bool test() {
+ test_converting_ctor<void, Bar>();
+ test_converting_ctor<void, int>();
+ test_converting_ctor<Base, Derived>();
+
+ check_non_constructible<Derived, Base>();
+ check_non_constructible<int, void>();
+ check_non_constructible<Bar, void>();
+ check_non_constructible<int, long>();
+ check_non_constructible<long, int>();
+
+ // Check const-ness
+ check_non_constructible<Bar, Bar const>();
+ test_converting_ctor<Bar const, Bar>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.copy_move.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.copy_move.cpp
new file mode 100644
index 000000000000000..acfa41d0bb1aa7c
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.copy_move.cpp
@@ -0,0 +1,60 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// observer_ptr(const observer_ptr& other) = default;
+// observer_ptr(observer_ptr&& other) = default;
+
+#include <experimental/memory>
+#include <cassert>
+#include <type_traits>
+#include <utility>
+
+template <class T, class Object = T>
+constexpr void test_copy_move() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj;
+ {
+ Ptr ptr(&obj);
+ Ptr copy = ptr;
+ assert(ptr.get() == &obj);
+ assert(copy.get() == &obj);
+ static_assert(std::is_nothrow_copy_constructible<Ptr>::value);
+ }
+ {
+ Ptr ptr(&obj);
+ Ptr copy = std::move(ptr);
+ assert(ptr.get() == &obj);
+ assert(copy.get() == &obj);
+ static_assert(std::is_nothrow_move_constructible<Ptr>::value);
+ }
+}
+
+struct Bar {};
+
+constexpr bool test() {
+ test_copy_move<int>();
+ test_copy_move<Bar>();
+ test_copy_move<void, int>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.default.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.default.pass.cpp
new file mode 100644
index 000000000000000..6d254418916d30d
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.default.pass.cpp
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr observer_ptr() noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T>
+constexpr void test_default_ctor() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Ptr ptr;
+ assert(ptr.get() == nullptr);
+ static_assert(std::is_nothrow_default_constructible<Ptr>::value);
+}
+
+struct Foo;
+struct Bar {
+ Bar(int) {}
+};
+
+constexpr bool test() {
+ test_default_ctor<Foo>();
+ test_default_ctor<Bar>();
+ test_default_ctor<int>();
+ test_default_ctor<void>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.element_type.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.element_type.pass.cpp
new file mode 100644
index 000000000000000..830f3664cae85ea
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.element_type.pass.cpp
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr explicit observer_ptr(element_type* p) noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class ObjectT = T>
+constexpr void test_element_type_ctor() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ ObjectT obj;
+ T* raw = &obj;
+ Ptr ptr(raw);
+ assert(ptr.get() == raw);
+ static_assert(!std::is_convertible<T*, Ptr>::value);
+ static_assert(std::is_nothrow_constructible<Ptr, T*>::value);
+}
+
+struct Bar {};
+
+constexpr bool test() {
+ test_element_type_ctor<Bar>();
+ test_element_type_ctor<int>();
+ test_element_type_ctor<void, int>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.nullptr.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.nullptr.pass.cpp
new file mode 100644
index 000000000000000..8940f1c263004c3
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/ctor.nullptr.pass.cpp
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr observer_ptr(nullptr_t) noexcept;
+
+#include <experimental/memory>
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+
+template <class T>
+constexpr void test_nullptr_ctor() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Ptr ptr = nullptr;
+ assert(ptr.get() == nullptr);
+ static_assert(std::is_nothrow_constructible<Ptr, std::nullptr_t>::value);
+}
+
+struct Foo;
+struct Bar {
+ Bar(int) {}
+};
+
+constexpr bool test() {
+ test_nullptr_ctor<Foo>();
+ test_nullptr_ctor<Bar>();
+ test_nullptr_ctor<int>();
+ test_nullptr_ctor<void>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/deref.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/deref.pass.cpp
new file mode 100644
index 000000000000000..30b13066e4a96ad
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/deref.pass.cpp
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr std::add_lvalue_reference_t<element_type> operator*() const;
+// constexpr element_type* operator->() const noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class Object = T>
+constexpr void test_deref() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj;
+
+ {
+ Ptr const ptr(&obj);
+ T& r = *ptr;
+ assert(&r == &obj);
+ }
+ {
+ Ptr const ptr(&obj);
+ T* r = ptr.operator->();
+ assert(r == &obj);
+ static_assert(noexcept(ptr.operator->()));
+ }
+}
+
+struct Bar {};
+struct Foo {
+ int member = 42;
+};
+
+constexpr bool test() {
+ test_deref<Bar>();
+ test_deref<int>();
+
+ {
+ Foo foo;
+ std::experimental::observer_ptr<Foo> ptr(&foo);
+ assert(&ptr->member == &foo.member);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/get.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/get.pass.cpp
new file mode 100644
index 000000000000000..eae5d5180db93db
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/get.pass.cpp
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr element_type* get() const noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class Object = T>
+constexpr void test_get() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj;
+
+ Ptr const ptr(&obj);
+ assert(ptr.get() == &obj);
+
+ static_assert(noexcept(ptr.get()));
+ static_assert(std::is_same<decltype(ptr.get()), T*>::value);
+}
+
+struct Bar {};
+
+constexpr bool test() {
+ test_get<Bar>();
+ test_get<int>();
+ test_get<void, int>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/hash.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/hash.pass.cpp
new file mode 100644
index 000000000000000..7aa5dc8d5b326cc
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/hash.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// template <class T> struct hash<std::experimental::observer_ptr<T>>;
+
+#include <experimental/memory>
+#include <cassert>
+
+#include "poisoned_hash_helper.h"
+
+template <class T, class Object = T>
+void test_hash() {
+ {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj;
+ Ptr ptr(&obj);
+
+ std::hash<std::experimental::observer_ptr<T>> f;
+ std::size_t h = f(ptr);
+
+ assert(h == std::hash<T*>()(&obj));
+ }
+
+ test_hash_enabled_for_type<std::experimental::observer_ptr<T>>();
+}
+
+struct Bar {};
+
+void test() {
+ test_hash<void, int>();
+ test_hash<int>();
+ test_hash<Bar>();
+}
+
+int main(int, char**) {
+ // Note: This isn't constexpr friendly in the spec!
+ test();
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/make_observer.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/make_observer.pass.cpp
new file mode 100644
index 000000000000000..8a530fb0e0136ad
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/make_observer.pass.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// template <class W>
+// std::experimental::observer_ptr<W> make_observer(W* p) noexcept;
+
+#include <experimental/memory>
+#include <cassert>
+#include <type_traits>
+
+template <class T, class Object = T>
+void test_make_observer() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj;
+ T* raw = &obj;
+
+ Ptr ptr = std::experimental::make_observer(raw);
+ assert(ptr.get() == raw);
+ static_assert(noexcept(std::experimental::make_observer(raw)));
+ static_assert(std::is_same<decltype(std::experimental::make_observer(raw)), Ptr>::value);
+}
+
+struct Bar {};
+
+void test() {
+ test_make_observer<void, int>();
+ test_make_observer<int>();
+ test_make_observer<Bar>();
+}
+
+int main(int, char**) {
+ // Note: this is not constexpr in the spec
+ test();
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/operator-bool.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/operator-bool.pass.cpp
new file mode 100644
index 000000000000000..b44f7c8bd2ee528
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/operator-bool.pass.cpp
@@ -0,0 +1,61 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr explicit operator bool() const noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class Object = T>
+constexpr void test_operator_bool() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj;
+
+ {
+ Ptr const ptr(&obj);
+ bool b = static_cast<bool>(ptr);
+ assert(b);
+
+ static_assert(noexcept(static_cast<bool>(ptr)));
+ }
+
+ {
+ Ptr const ptr(nullptr);
+ bool b = static_cast<bool>(ptr);
+ assert(!b);
+ }
+
+ static_assert(!std::is_convertible<Ptr const, bool>::value);
+ static_assert(std::is_constructible<bool, Ptr const>::value);
+}
+
+struct Bar {};
+
+constexpr bool test() {
+ test_operator_bool<Bar>();
+ test_operator_bool<int>();
+ test_operator_bool<void, int>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/operator-element_type.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/operator-element_type.pass.cpp
new file mode 100644
index 000000000000000..6e5bcd6aca6e88d
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/operator-element_type.pass.cpp
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr explicit operator element_type*() const noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class Object = T>
+constexpr void test_convertibility() {
+ Object obj;
+ std::experimental::observer_ptr<T> ptr(&obj);
+
+ T* raw = static_cast<T*>(ptr);
+ assert(raw == &obj);
+ static_assert(!std::is_convertible<std::experimental::observer_ptr<T>, T*>::value, "");
+ static_assert(std::is_constructible<T*, std::experimental::observer_ptr<T>>::value, "");
+}
+
+struct Incomplete;
+
+struct Bar {};
+
+constexpr bool test() {
+ test_convertibility<void, int>();
+ test_convertibility<bool>();
+ test_convertibility<int>();
+ test_convertibility<Bar>();
+
+ {
+ std::experimental::observer_ptr<Incomplete> ptr = nullptr;
+ Incomplete* raw = static_cast<Incomplete*>(ptr);
+ assert(raw == nullptr);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/release.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/release.pass.cpp
new file mode 100644
index 000000000000000..a6000f7cce89852
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/release.pass.cpp
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr element_type* release() noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class Object = T>
+constexpr void test_release() {
+ Object obj;
+ using Ptr = std::experimental::observer_ptr<T>;
+ Ptr ptr(&obj);
+ assert(ptr.get() == &obj);
+
+ decltype(auto) r = ptr.release();
+ assert(r == &obj);
+ assert(ptr.get() == nullptr);
+
+ static_assert(std::is_same<decltype(r), typename Ptr::element_type*>::value);
+ static_assert(noexcept(ptr.release()));
+}
+
+struct Bar {};
+
+constexpr bool test() {
+ test_release<Bar>();
+ test_release<int>();
+ test_release<void, int>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/reset.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/reset.pass.cpp
new file mode 100644
index 000000000000000..0a639d6e000c0c4
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/reset.pass.cpp
@@ -0,0 +1,61 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr void reset(element_type* p = nullptr) noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class Object = T>
+constexpr void test_reset() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj1, obj2;
+
+ {
+ Ptr ptr(&obj1);
+ assert(ptr.get() == &obj1);
+ ptr.reset(&obj2);
+ assert(ptr.get() == &obj2);
+ static_assert(noexcept(ptr.reset(&obj2)));
+ static_assert(std::is_same<decltype(ptr.reset(&obj2)), void>::value);
+ }
+ {
+ Ptr ptr(&obj1);
+ assert(ptr.get() == &obj1);
+ ptr.reset();
+ assert(ptr.get() == nullptr);
+ static_assert(noexcept(ptr.reset()));
+ static_assert(std::is_same<decltype(ptr.reset()), void>::value);
+ }
+}
+
+struct Bar {};
+
+constexpr bool test() {
+ test_reset<Bar>();
+ test_reset<int>();
+ test_reset<void, int>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/swap.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/swap.pass.cpp
new file mode 100644
index 000000000000000..ffd43a750e2ef29
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/swap.pass.cpp
@@ -0,0 +1,79 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// constexpr void swap(observer_ptr& other) noexcept;
+//
+// template <class W>
+// void swap(observer_ptr<W>& lhs, observer_ptr<W>& rhs) noexcept;
+
+#include <experimental/memory>
+#include <type_traits>
+#include <cassert>
+
+template <class T, class Object = T>
+constexpr void test_swap() {
+ using Ptr = std::experimental::observer_ptr<T>;
+ Object obj1, obj2;
+
+ {
+ Ptr ptr1(&obj1);
+ Ptr ptr2(&obj2);
+
+ assert(ptr1.get() == &obj1);
+ assert(ptr2.get() == &obj2);
+
+ ptr1.swap(ptr2);
+
+ assert(ptr1.get() == &obj2);
+ assert(ptr2.get() == &obj1);
+
+ static_assert(noexcept(ptr1.swap(ptr2)));
+ static_assert(std::is_same<decltype(ptr1.swap(ptr2)), void>::value);
+ }
+
+ {
+ Ptr ptr1(&obj1);
+ Ptr ptr2(&obj2);
+
+ assert(ptr1.get() == &obj1);
+ assert(ptr2.get() == &obj2);
+
+ std::experimental::swap(ptr1, ptr2);
+
+ assert(ptr1.get() == &obj2);
+ assert(ptr2.get() == &obj1);
+
+ static_assert(noexcept(std::experimental::swap(ptr1, ptr2)));
+ static_assert(std::is_same<decltype(std::experimental::swap(ptr1, ptr2)), void>::value);
+ }
+}
+
+struct Bar {};
+
+constexpr bool test() {
+ test_swap<Bar>();
+ test_swap<int>();
+ test_swap<void, int>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/experimental/memory/memory.observer.ptr/types.compile.pass.cpp b/libcxx/test/std/experimental/memory/memory.observer.ptr/types.compile.pass.cpp
new file mode 100644
index 000000000000000..3d1461ca5a1208d
--- /dev/null
+++ b/libcxx/test/std/experimental/memory/memory.observer.ptr/types.compile.pass.cpp
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: c++experimental
+
+// <experimental/memory>
+
+// observer_ptr
+//
+// using element_type = W;
+
+#include <experimental/memory>
+#include <type_traits>
+
+using T = std::experimental::observer_ptr<int>::element_type;
+static_assert(std::is_same<T, int>::value);
More information about the libcxx-commits
mailing list