diff --git a/libcxx/docs/Status/Cxx17Issues.csv b/libcxx/docs/Status/Cxx17Issues.csv --- a/libcxx/docs/Status/Cxx17Issues.csv +++ b/libcxx/docs/Status/Cxx17Issues.csv @@ -143,7 +143,7 @@ "`2441 `__","Exact-width atomic typedefs should be provided","Oulu","|Complete|","" "`2451 `__","[fund.ts.v2] optional should 'forward' T's implicit conversions","Oulu","|Nothing To Do|","" "`2509 `__","[fund.ts.v2] any_cast doesn't work with rvalue reference targets and cannot move with a value target","Oulu","|Complete|","" -"`2516 `__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","Oulu","","" +"`2516 `__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","Oulu","|Complete|","18.0" "`2542 `__","Missing const requirements for associative containers","Oulu","","" "`2549 `__","Tuple EXPLICIT constructor templates that take tuple parameters end up taking references to temporaries and will create dangling references","Oulu","|Complete|","" "`2550 `__","Wording of unordered container's clear() method complexity","Oulu","|Complete|","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -924,6 +924,7 @@ 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 --- a/libcxx/include/__std_clang_module +++ b/libcxx/include/__std_clang_module @@ -91,6 +91,7 @@ #include #include #include +#include #include #include #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) diff --git a/libcxx/include/experimental/memory b/libcxx/include/experimental/memory new file mode 100644 --- /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 observer_ptr { +public: + using element_type = W; + using pointer = add_pointer_t; // exposition-only + using reference = add_lvalue_reference_t; // 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 constexpr observer_ptr(observer_ptr) 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 +#include + +#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 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 ::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 +_LIBCPP_HIDE_FROM_ABI constexpr void swap(observer_ptr<_Wp>& __a, observer_ptr<_Wp>& __b) noexcept { + __a.swap(__b); +} + +template +_LIBCPP_HIDE_FROM_ABI observer_ptr<_Wp> make_observer(_Wp* __ptr) noexcept { + return observer_ptr<_Wp>{__ptr}; +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_W1> __a, observer_ptr<_W2> __b) { + return __a.get() == __b.get(); +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) { + return !(__a == __b); +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_Wp> __p, nullptr_t) { + return !__p; +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, observer_ptr<_Wp> __p) { + return !__p; +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_Wp> __p, nullptr_t) { + return (bool)__p; +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, observer_ptr<_Wp> __p) { + return (bool)__p; +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator<(observer_ptr<_W1> __a, observer_ptr<_W2> __b) { + return std::less::type>()(__a.get(), __b.get()); +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator>(observer_ptr<_W1> __a, observer_ptr<_W2> __b) { + return __b < __a; +} + +template +_LIBCPP_HIDE_FROM_ABI bool operator<=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) { + return !(__a > __b); +} + +template +_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 +struct hash> { + _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 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -533,6 +533,10 @@ 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 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -240,6 +240,10 @@ 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 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -241,6 +241,10 @@ 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 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -241,6 +241,10 @@ 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 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -241,6 +241,10 @@ 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 --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -247,6 +247,10 @@ 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 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -176,6 +176,10 @@ 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 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -176,6 +176,10 @@ 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 --- /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 + +// + +// observer_ptr +// +// template +// bool operator==(const observer_ptr& p1, const observer_ptr& p2); +// +// template +// bool operator!=(const observer_ptr& p1, const observer_ptr& p2); +// +// template +// bool operator==(const observer_ptr& p, std::nullptr_t) noexcept; +// +// template +// bool operator==(std::nullptr_t, const observer_ptr& p) noexcept; +// +// template +// bool operator!=(const observer_ptr& p, std::nullptr_t) noexcept; +// +// template +// bool operator!=(std::nullptr_t, const observer_ptr& p) noexcept; +// +// template +// bool operator<(const observer_ptr& p1, const observer_ptr& p2); +// +// template +// bool operator>(const observer_ptr& p1, const observer_ptr& p2); +// +// template +// bool operator<=(const observer_ptr& p1, const observer_ptr& p2); +// +// template +// bool operator>=(const observer_ptr& p1, const observer_ptr& p2); + +#include +#include + +void test() { + using T = int; + using Ptr = std::experimental::observer_ptr; + using VoidPtr = std::experimental::observer_ptr; + + // 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 --- /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 + +// + +// observer_ptr +// +// template +// constexpr observer_ptr(observer_ptr other) noexcept; + +#include +#include +#include + +#include "test_macros.h" + +template +constexpr void test_converting_ctor() { + using ToPtr = std::experimental::observer_ptr; + using FromPtr = std::experimental::observer_ptr; + 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::value); +#endif +} + +template +constexpr void check_non_constructible() { + using ToPtr = std::experimental::observer_ptr; + using FromPtr = std::experimental::observer_ptr; + static_assert(!std::is_constructible::value); +} + +struct Bar {}; +struct Base {}; +struct Derived : Base {}; + +constexpr bool test() { + test_converting_ctor(); + test_converting_ctor(); + test_converting_ctor(); + + check_non_constructible(); + check_non_constructible(); + check_non_constructible(); + check_non_constructible(); + check_non_constructible(); + + // Check const-ness + check_non_constructible(); + test_converting_ctor(); + + 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 --- /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 + +// + +// observer_ptr +// +// observer_ptr(const observer_ptr& other) = default; +// observer_ptr(observer_ptr&& other) = default; + +#include +#include +#include +#include + +template +constexpr void test_copy_move() { + using Ptr = std::experimental::observer_ptr; + Object obj; + { + Ptr ptr(&obj); + Ptr copy = ptr; + assert(ptr.get() == &obj); + assert(copy.get() == &obj); + static_assert(std::is_nothrow_copy_constructible::value); + } + { + Ptr ptr(&obj); + Ptr copy = std::move(ptr); + assert(ptr.get() == &obj); + assert(copy.get() == &obj); + static_assert(std::is_nothrow_move_constructible::value); + } +} + +struct Bar {}; + +constexpr bool test() { + test_copy_move(); + test_copy_move(); + test_copy_move(); + + 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 --- /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 + +// + +// observer_ptr +// +// constexpr observer_ptr() noexcept; + +#include +#include +#include + +template +constexpr void test_default_ctor() { + using Ptr = std::experimental::observer_ptr; + Ptr ptr; + assert(ptr.get() == nullptr); + static_assert(std::is_nothrow_default_constructible::value); +} + +struct Foo; +struct Bar { + Bar(int) {} +}; + +constexpr bool test() { + test_default_ctor(); + test_default_ctor(); + test_default_ctor(); + test_default_ctor(); + + 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 --- /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 + +// + +// observer_ptr +// +// constexpr explicit observer_ptr(element_type* p) noexcept; + +#include +#include +#include + +template +constexpr void test_element_type_ctor() { + using Ptr = std::experimental::observer_ptr; + ObjectT obj; + T* raw = &obj; + Ptr ptr(raw); + assert(ptr.get() == raw); + static_assert(!std::is_convertible::value); + static_assert(std::is_nothrow_constructible::value); +} + +struct Bar {}; + +constexpr bool test() { + test_element_type_ctor(); + test_element_type_ctor(); + test_element_type_ctor(); + + 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 --- /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 + +// + +// observer_ptr +// +// constexpr observer_ptr(nullptr_t) noexcept; + +#include +#include +#include +#include + +template +constexpr void test_nullptr_ctor() { + using Ptr = std::experimental::observer_ptr; + Ptr ptr = nullptr; + assert(ptr.get() == nullptr); + static_assert(std::is_nothrow_constructible::value); +} + +struct Foo; +struct Bar { + Bar(int) {} +}; + +constexpr bool test() { + test_nullptr_ctor(); + test_nullptr_ctor(); + test_nullptr_ctor(); + test_nullptr_ctor(); + + 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 --- /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 + +// + +// observer_ptr +// +// constexpr std::add_lvalue_reference_t operator*() const; +// constexpr element_type* operator->() const noexcept; + +#include +#include +#include + +template +constexpr void test_deref() { + using Ptr = std::experimental::observer_ptr; + 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(); + test_deref(); + + { + Foo foo; + std::experimental::observer_ptr 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 --- /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 + +// + +// observer_ptr +// +// constexpr element_type* get() const noexcept; + +#include +#include +#include + +template +constexpr void test_get() { + using Ptr = std::experimental::observer_ptr; + Object obj; + + Ptr const ptr(&obj); + assert(ptr.get() == &obj); + + static_assert(noexcept(ptr.get())); + static_assert(std::is_same::value); +} + +struct Bar {}; + +constexpr bool test() { + test_get(); + test_get(); + test_get(); + + 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 --- /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 + +// + +// observer_ptr +// +// template struct hash>; + +#include +#include + +#include "poisoned_hash_helper.h" + +template +void test_hash() { + { + using Ptr = std::experimental::observer_ptr; + Object obj; + Ptr ptr(&obj); + + std::hash> f; + std::size_t h = f(ptr); + + assert(h == std::hash()(&obj)); + } + + test_hash_enabled_for_type>(); +} + +struct Bar {}; + +void test() { + test_hash(); + test_hash(); + test_hash(); +} + +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 --- /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 + +// + +// observer_ptr +// +// template +// std::experimental::observer_ptr make_observer(W* p) noexcept; + +#include +#include +#include + +template +void test_make_observer() { + using Ptr = std::experimental::observer_ptr; + 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::value); +} + +struct Bar {}; + +void test() { + test_make_observer(); + test_make_observer(); + test_make_observer(); +} + +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 --- /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 + +// + +// observer_ptr +// +// constexpr explicit operator bool() const noexcept; + +#include +#include +#include + +template +constexpr void test_operator_bool() { + using Ptr = std::experimental::observer_ptr; + Object obj; + + { + Ptr const ptr(&obj); + bool b = static_cast(ptr); + assert(b); + + static_assert(noexcept(static_cast(ptr))); + } + + { + Ptr const ptr(nullptr); + bool b = static_cast(ptr); + assert(!b); + } + + static_assert(!std::is_convertible::value); + static_assert(std::is_constructible::value); +} + +struct Bar {}; + +constexpr bool test() { + test_operator_bool(); + test_operator_bool(); + test_operator_bool(); + + 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 --- /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 + +// + +// observer_ptr +// +// constexpr explicit operator element_type*() const noexcept; + +#include +#include +#include + +template +constexpr void test_convertibility() { + Object obj; + std::experimental::observer_ptr ptr(&obj); + + T* raw = static_cast(ptr); + assert(raw == &obj); + static_assert(!std::is_convertible, T*>::value, ""); + static_assert(std::is_constructible>::value, ""); +} + +struct Incomplete; + +struct Bar {}; + +constexpr bool test() { + test_convertibility(); + test_convertibility(); + test_convertibility(); + test_convertibility(); + + { + std::experimental::observer_ptr ptr = nullptr; + Incomplete* raw = static_cast(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 --- /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 + +// + +// observer_ptr +// +// constexpr element_type* release() noexcept; + +#include +#include +#include + +template +constexpr void test_release() { + Object obj; + using Ptr = std::experimental::observer_ptr; + Ptr ptr(&obj); + assert(ptr.get() == &obj); + + decltype(auto) r = ptr.release(); + assert(r == &obj); + assert(ptr.get() == nullptr); + + static_assert(std::is_same::value); + static_assert(noexcept(ptr.release())); +} + +struct Bar {}; + +constexpr bool test() { + test_release(); + test_release(); + test_release(); + + 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 --- /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 + +// + +// observer_ptr +// +// constexpr void reset(element_type* p = nullptr) noexcept; + +#include +#include +#include + +template +constexpr void test_reset() { + using Ptr = std::experimental::observer_ptr; + 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::value); + } + { + Ptr ptr(&obj1); + assert(ptr.get() == &obj1); + ptr.reset(); + assert(ptr.get() == nullptr); + static_assert(noexcept(ptr.reset())); + static_assert(std::is_same::value); + } +} + +struct Bar {}; + +constexpr bool test() { + test_reset(); + test_reset(); + test_reset(); + + 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 --- /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 + +// + +// observer_ptr +// +// constexpr void swap(observer_ptr& other) noexcept; +// +// template +// void swap(observer_ptr& lhs, observer_ptr& rhs) noexcept; + +#include +#include +#include + +template +constexpr void test_swap() { + using Ptr = std::experimental::observer_ptr; + 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::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::value); + } +} + +struct Bar {}; + +constexpr bool test() { + test_swap(); + test_swap(); + test_swap(); + + 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 --- /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 + +// + +// observer_ptr +// +// using element_type = W; + +#include +#include + +using T = std::experimental::observer_ptr::element_type; +static_assert(std::is_same::value);