| // Part of the Crubit project, under the Apache License v2.0 with LLVM |
| // Exceptions. See /LICENSE for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| |
| // Mock of standard library <memory> header. |
| |
| #ifndef CRUBIT_NULLABILITY_TEST_MEMORY_ |
| #define CRUBIT_NULLABILITY_TEST_MEMORY_ |
| |
| namespace std { |
| |
| // Adding some definitions here for convenience that really belong in other |
| // headers. |
| |
| using nullptr_t = decltype(nullptr); |
| |
| using size_t = decltype(sizeof(int)); |
| |
| template <class T> |
| struct remove_extent { using type = T; }; |
| template <class T> |
| struct remove_extent<T[]> { using type = T; }; |
| template <class T, size_t N> |
| struct remove_extent<T[N]> { using type = T; }; |
| |
| template <class T> struct default_delete{}; |
| template <class T> struct allocator{}; |
| |
| template< class... > |
| using void_t = void; |
| |
| template <class T, class Deleter, class = void> |
| struct __underlying_ptr_type { |
| using type = T *; |
| }; |
| |
| template <class T, class Deleter> |
| // The standard says we should apply `std::remove_reference` to `Deleter`, |
| // but we don't need this for our tests, so we omit it for simplicity. |
| struct __underlying_ptr_type<T, Deleter, |
| std::void_t<typename Deleter::pointer>> { |
| using type = typename Deleter::pointer; |
| }; |
| |
| template <class T, class Deleter = default_delete<T>> |
| class unique_ptr { |
| public: |
| using pointer = __underlying_ptr_type<T, Deleter>::type; |
| |
| unique_ptr(); |
| unique_ptr(nullptr_t); |
| unique_ptr(pointer); |
| // We're restricting ourselves to just one possible case for the deleter |
| // parameter. |
| unique_ptr(pointer, const Deleter &); |
| unique_ptr(unique_ptr &&); |
| template <class OtherT, class OtherDeleter> |
| unique_ptr(unique_ptr<OtherT, OtherDeleter> &&); |
| unique_ptr(const unique_ptr &) = delete; |
| |
| // Make sure `unique_ptr` is not trivially destructible so that the AST for |
| // expressions using this mock look the same as for the real class. |
| ~unique_ptr(); |
| |
| unique_ptr &operator=(unique_ptr &&); |
| template <class OtherT, class OtherDeleter> |
| unique_ptr &operator=(unique_ptr<OtherT, OtherDeleter> &&); |
| unique_ptr &operator=(nullptr_t); |
| unique_ptr &operator=(const unique_ptr &) = delete; |
| |
| T &operator*() const; |
| T *operator->() const; |
| |
| pointer release(); |
| |
| void reset(pointer p = pointer()); |
| |
| void swap(unique_ptr &); |
| |
| pointer get() const; |
| |
| explicit operator bool() const; |
| }; |
| |
| // Array specialization of `unique_ptr`. We only introduce the members that are |
| // used in tests. |
| template <class T, class Deleter> |
| class unique_ptr<T[], Deleter> { |
| public: |
| using pointer = T*; |
| |
| unique_ptr(); |
| template <class ArrayT> |
| explicit unique_ptr(ArrayT); |
| template <class ArrayT> |
| explicit unique_ptr(ArrayT, const Deleter &); |
| unique_ptr(const unique_ptr &) = delete; |
| |
| ~unique_ptr(); |
| |
| template <class ArrayT> |
| void reset(ArrayT); |
| void reset(nullptr_t = nullptr); |
| |
| pointer get() const; |
| |
| T &operator[](size_t) const; |
| }; |
| |
| // We're restricting ourselves to just some of the overloads that are required |
| // to provide sufficient test coverage. |
| template <class T, class... Args> |
| unique_ptr<T> make_unique(Args &&...args); |
| template <class T> |
| unique_ptr<T> make_unique_for_overwrite(); |
| template <class T> |
| unique_ptr<T> make_unique_for_overwrite(size_t); |
| |
| template <class T, class Deleter> |
| void swap(unique_ptr<T, Deleter> &, unique_ptr<T, Deleter> &); |
| |
| template <class T> |
| bool operator==(const unique_ptr<T> &, std::nullptr_t); |
| |
| // C++20 and later do not define the following overloads because they are |
| // provided by rewritten candidates instead. |
| #if __cplusplus < 202002L |
| template <class T> |
| bool operator==(std::nullptr_t, const unique_ptr<T> &); |
| #endif // __cplusplus < 202002L |
| |
| template <class T> class weak_ptr; |
| |
| // This definition of `shared_ptr` only introduces the members that are used in |
| // tests. |
| template <class T> |
| class shared_ptr { |
| public: |
| using element_type = typename remove_extent<T>::type; |
| |
| shared_ptr(); |
| template <class OtherT> |
| shared_ptr(OtherT *); |
| template <class Deleter> |
| shared_ptr(nullptr_t, Deleter); |
| template <class Deleter, class Alloc> |
| shared_ptr(nullptr_t, Deleter, Alloc); |
| template <class OtherT, class Deleter, class Alloc> |
| shared_ptr(OtherT *, Deleter, Alloc); |
| template <class OtherT> |
| shared_ptr(const shared_ptr<OtherT> &, element_type *); |
| template <class OtherT> |
| shared_ptr(shared_ptr<OtherT> &&, element_type *); |
| shared_ptr(const shared_ptr &); |
| template <class OtherT> |
| explicit shared_ptr(const weak_ptr<OtherT> &); |
| template <class OtherT, class Deleter> |
| explicit shared_ptr(unique_ptr<OtherT, Deleter> &&); |
| |
| ~shared_ptr(); |
| |
| shared_ptr &operator=(const shared_ptr &); |
| template <class OtherT> |
| shared_ptr &operator=(const shared_ptr<OtherT> &); |
| |
| T& operator*() const; |
| |
| void reset(); |
| template <class OtherT> |
| void reset(OtherT *); |
| template <class OtherT, class Deleter> |
| void reset(OtherT *, Deleter); |
| template <class OtherT, class Deleter, class Alloc> |
| void reset(OtherT *, Deleter, Alloc); |
| |
| element_type* get() const; |
| |
| explicit operator bool() const; |
| }; |
| |
| // We're restricting ourselves to just some of the overloads that are required |
| // to provide sufficient test coverage. |
| template <class T> |
| shared_ptr<T> make_shared(); |
| template <class T, class... Args> |
| shared_ptr<T> make_shared(Args &&...args); |
| template <class T> |
| shared_ptr<T> make_shared_for_overwrite(); |
| template <class T> |
| shared_ptr<T> make_shared_for_overwrite(size_t); |
| |
| template <class T, class Alloc> |
| shared_ptr<T> allocate_shared(const Alloc &); |
| template <class T, class Alloc, class... Args> |
| shared_ptr<T> allocate_shared(const Alloc &, Args &&...args); |
| template <class T, class Alloc> |
| shared_ptr<T> allocate_shared_for_overwrite(const Alloc &); |
| template <class T, class Alloc> |
| shared_ptr<T> allocate_shared_for_overwrite(const Alloc &, size_t); |
| |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> static_pointer_cast(const shared_ptr<SrcT> &); |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> static_pointer_cast(const shared_ptr<SrcT> &&); |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> dynamic_pointer_cast(const shared_ptr<SrcT> &); |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> dynamic_pointer_cast(const shared_ptr<SrcT> &&); |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> const_pointer_cast(const shared_ptr<SrcT> &); |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> const_pointer_cast(const shared_ptr<SrcT> &&); |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> reinterpret_pointer_cast(const shared_ptr<SrcT> &); |
| template <class DestT, class SrcT> |
| shared_ptr<DestT> reinterpret_pointer_cast(const shared_ptr<SrcT> &&); |
| |
| template <class T1, class T2> |
| bool operator==(const shared_ptr<T1> &, const shared_ptr<T2> &); |
| template <class T> |
| bool operator==(const shared_ptr<T> &, std::nullptr_t); |
| |
| // C++20 and later do not define the following overloads because they are |
| // provided by rewritten candidates instead. |
| #if __cplusplus < 202002L |
| template <class T1, class T2> |
| bool operator!=(const shared_ptr<T1> &, const shared_ptr<T2> &); |
| template <class T> |
| bool operator==(std::nullptr_t, const shared_ptr<T> &); |
| template <class T> |
| bool operator!=(const shared_ptr<T> &, std::nullptr_t); |
| template <class T> |
| bool operator!=(std::nullptr_t, const shared_ptr<T> &); |
| #endif // __cplusplus < 202002L |
| |
| // This mock only provides the definitions needed to test that |
| // `weak_ptr::lock()` returns a nullable pointer. |
| template <class T> class weak_ptr { |
| public: |
| template <class OtherT> |
| weak_ptr(const shared_ptr<OtherT> &); |
| shared_ptr<T> lock() const; |
| }; |
| |
| } // namespace std |
| |
| #endif // CRUBIT_NULLABILITY_TEST_MEMORY_ |