blob: e04d3701830496f8d04d301f34f64b57e3d2ec8e [file] [log] [blame] [edit]
// 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_