Add __gnu_test::NullablePointer utility to testsuite
* testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc: Use operator-> to access raw pointer member. * testsuite/23_containers/vector/59829.cc: Likewise. * testsuite/23_containers/vector/bool/80893.cc: Likewise. * testsuite/libstdc++-prettyprinters/cxx11.cc: Use NullablePointer. * testsuite/util/testsuite_allocator.h (NullablePointer): New utility for tests. (PointerBase, PointerBase_void): Derive from NullablePointer and use its constructors and equality operators. Change converting constructors to use operator-> to access private member of the other pointer type. (PointerBase_void::operator->()): Add, for access to private member. (operator-(PointerBase, PointerBase)): Change to hidden friend. (operator==(PointerBase, PointerBase)): Remove. (operator!=(PointerBase, PointerBase)): Remove. From-SVN: r271160
This commit is contained in:
parent
e25f488d60
commit
066f9ea279
|
@ -1,5 +1,21 @@
|
|||
2019-05-14 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc:
|
||||
Use operator-> to access raw pointer member.
|
||||
* testsuite/23_containers/vector/59829.cc: Likewise.
|
||||
* testsuite/23_containers/vector/bool/80893.cc: Likewise.
|
||||
* testsuite/libstdc++-prettyprinters/cxx11.cc: Use NullablePointer.
|
||||
* testsuite/util/testsuite_allocator.h (NullablePointer): New utility
|
||||
for tests.
|
||||
(PointerBase, PointerBase_void): Derive from NullablePointer and use
|
||||
its constructors and equality operators. Change converting
|
||||
constructors to use operator-> to access private member of the other
|
||||
pointer type.
|
||||
(PointerBase_void::operator->()): Add, for access to private member.
|
||||
(operator-(PointerBase, PointerBase)): Change to hidden friend.
|
||||
(operator==(PointerBase, PointerBase)): Remove.
|
||||
(operator!=(PointerBase, PointerBase)): Remove.
|
||||
|
||||
* python/libstdcxx/v6/printers.py (UniquePointerPrinter.__init__): Do
|
||||
not assume field called _M_head_impl is the first tuple element.
|
||||
* testsuite/libstdc++-prettyprinters/compat.cc: Make tuple
|
||||
|
|
|
@ -45,7 +45,7 @@ struct Alloc
|
|||
{ return pointer(std::allocator<T>().allocate(n)); }
|
||||
|
||||
void deallocate(pointer p, std::size_t n)
|
||||
{ std::allocator<T>().deallocate(p.value, n); }
|
||||
{ std::allocator<T>().deallocate(p.operator->(), n); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -51,7 +51,7 @@ struct Alloc
|
|||
{ return pointer(std::allocator<T>().allocate(n)); }
|
||||
|
||||
void deallocate(pointer p, std::size_t n)
|
||||
{ std::allocator<T>().deallocate(p.value, n); }
|
||||
{ std::allocator<T>().deallocate(p.operator->(), n); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -59,7 +59,7 @@ struct Alloc
|
|||
void deallocate(pointer p, std::size_t n)
|
||||
{
|
||||
if (n)
|
||||
std::allocator<T>().deallocate(p.value, n);
|
||||
std::allocator<T>().deallocate(p.operator->(), n);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include "../util/testsuite_allocator.h" // NullablePointer
|
||||
|
||||
typedef std::tuple<int, int> ExTuple;
|
||||
|
||||
|
@ -59,21 +60,6 @@ struct datum
|
|||
|
||||
std::unique_ptr<datum> global;
|
||||
|
||||
struct Deleter
|
||||
{
|
||||
// Deleter is not an empty class:
|
||||
int deleter_member = -1;
|
||||
// But pointer is an empty class:
|
||||
struct pointer
|
||||
{
|
||||
pointer(const void* = nullptr) { }
|
||||
explicit operator bool() const noexcept { return false; }
|
||||
friend bool operator==(pointer, pointer) noexcept { return true; }
|
||||
friend bool operator!=(pointer, pointer) noexcept { return false; }
|
||||
};
|
||||
void operator()(pointer) const noexcept { }
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
@ -151,6 +137,15 @@ main()
|
|||
std::unique_ptr<data>& rarrptr = arrptr;
|
||||
// { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } }
|
||||
|
||||
struct Deleter
|
||||
{
|
||||
int deleter_member = -1;
|
||||
using pointer = __gnu_test::NullablePointer<void>;
|
||||
void operator()(pointer) const noexcept { }
|
||||
};
|
||||
static_assert( !std::is_empty<Deleter>(), "Deleter is not empty" );
|
||||
static_assert( std::is_empty<Deleter::pointer>(), "but pointer is empty" );
|
||||
|
||||
std::unique_ptr<int, Deleter> empty_ptr;
|
||||
// { dg-final { note-test empty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
|
||||
std::unique_ptr<int, Deleter>& rempty_ptr = empty_ptr;
|
||||
|
|
|
@ -589,9 +589,54 @@ namespace __gnu_test
|
|||
{ std::allocator<Tp>::deallocate(std::addressof(*p), n); }
|
||||
};
|
||||
|
||||
// A class type meeting *only* the Cpp17NullablePointer requirements.
|
||||
// Can be used as a base class for fancy pointers (like PointerBase, below)
|
||||
// or to wrap a built-in pointer type to remove operations not required
|
||||
// by the Cpp17NullablePointer requirements (dereference, increment etc.)
|
||||
template<typename Ptr>
|
||||
struct NullablePointer
|
||||
{
|
||||
// N.B. default constructor does not initialize value
|
||||
NullablePointer() = default;
|
||||
NullablePointer(std::nullptr_t) noexcept : value() { }
|
||||
|
||||
explicit operator bool() const noexcept { return value == nullptr; }
|
||||
|
||||
friend inline bool
|
||||
operator==(NullablePointer lhs, NullablePointer rhs) noexcept
|
||||
{ return lhs.value == rhs.value; }
|
||||
|
||||
friend inline bool
|
||||
operator!=(NullablePointer lhs, NullablePointer rhs) noexcept
|
||||
{ return lhs.value != rhs.value; }
|
||||
|
||||
protected:
|
||||
explicit NullablePointer(Ptr p) noexcept : value(p) { }
|
||||
Ptr value;
|
||||
};
|
||||
|
||||
// NullablePointer<void> is an empty type that models Cpp17NullablePointer.
|
||||
template<>
|
||||
struct NullablePointer<void>
|
||||
{
|
||||
NullablePointer() = default;
|
||||
NullablePointer(std::nullptr_t) noexcept { }
|
||||
explicit NullablePointer(const volatile void*) noexcept { }
|
||||
|
||||
explicit operator bool() const noexcept { return false; }
|
||||
|
||||
friend inline bool
|
||||
operator==(NullablePointer, NullablePointer) noexcept
|
||||
{ return true; }
|
||||
|
||||
friend inline bool
|
||||
operator!=(NullablePointer, NullablePointer) noexcept
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
// Utility for use as CRTP base class of custom pointer types
|
||||
template<typename Derived, typename T>
|
||||
struct PointerBase
|
||||
struct PointerBase : NullablePointer<T*>
|
||||
{
|
||||
typedef T element_type;
|
||||
|
||||
|
@ -602,29 +647,38 @@ namespace __gnu_test
|
|||
typedef Derived pointer;
|
||||
typedef T& reference;
|
||||
|
||||
T* value;
|
||||
using NullablePointer<T*>::NullablePointer;
|
||||
|
||||
explicit PointerBase(T* p = nullptr) : value(p) { }
|
||||
|
||||
PointerBase(std::nullptr_t) : value(nullptr) { }
|
||||
// Public (but explicit) constructor from raw pointer:
|
||||
explicit PointerBase(T* p) noexcept : NullablePointer<T*>(p) { }
|
||||
|
||||
template<typename D, typename U,
|
||||
typename = decltype(static_cast<T*>(std::declval<U*>()))>
|
||||
PointerBase(const PointerBase<D, U>& p) : value(p.value) { }
|
||||
PointerBase(const PointerBase<D, U>& p)
|
||||
: NullablePointer<T*>(p.operator->()) { }
|
||||
|
||||
T& operator*() const { return *value; }
|
||||
T* operator->() const { return value; }
|
||||
T& operator[](difference_type n) const { return value[n]; }
|
||||
T& operator*() const { return *this->value; }
|
||||
T* operator->() const { return this->value; }
|
||||
T& operator[](difference_type n) const { return this->value[n]; }
|
||||
|
||||
Derived& operator++() { ++value; return derived(); }
|
||||
Derived operator++(int) { Derived tmp(derived()); ++value; return tmp; }
|
||||
Derived& operator--() { --value; return derived(); }
|
||||
Derived operator--(int) { Derived tmp(derived()); --value; return tmp; }
|
||||
Derived& operator++() { ++this->value; return derived(); }
|
||||
Derived& operator--() { --this->value; return derived(); }
|
||||
|
||||
Derived& operator+=(difference_type n) { value += n; return derived(); }
|
||||
Derived& operator-=(difference_type n) { value -= n; return derived(); }
|
||||
Derived operator++(int) { return Derived(this->value++); }
|
||||
|
||||
explicit operator bool() const { return value != nullptr; }
|
||||
Derived operator--(int) { return Derived(this->value--); }
|
||||
|
||||
Derived& operator+=(difference_type n)
|
||||
{
|
||||
this->value += n;
|
||||
return derived();
|
||||
}
|
||||
|
||||
Derived& operator-=(difference_type n)
|
||||
{
|
||||
this->value -= n;
|
||||
return derived();
|
||||
}
|
||||
|
||||
Derived
|
||||
operator+(difference_type n) const
|
||||
|
@ -641,6 +695,9 @@ namespace __gnu_test
|
|||
}
|
||||
|
||||
private:
|
||||
friend std::ptrdiff_t operator-(PointerBase l, PointerBase r)
|
||||
{ return l.value - r.value; }
|
||||
|
||||
Derived&
|
||||
derived() { return static_cast<Derived&>(*this); }
|
||||
|
||||
|
@ -648,21 +705,9 @@ namespace __gnu_test
|
|||
derived() const { return static_cast<const Derived&>(*this); }
|
||||
};
|
||||
|
||||
template<typename D, typename T>
|
||||
std::ptrdiff_t operator-(PointerBase<D, T> l, PointerBase<D, T> r)
|
||||
{ return l.value - r.value; }
|
||||
|
||||
template<typename D, typename T>
|
||||
bool operator==(PointerBase<D, T> l, PointerBase<D, T> r)
|
||||
{ return l.value == r.value; }
|
||||
|
||||
template<typename D, typename T>
|
||||
bool operator!=(PointerBase<D, T> l, PointerBase<D, T> r)
|
||||
{ return l.value != r.value; }
|
||||
|
||||
// implementation for void specializations
|
||||
template<typename T>
|
||||
struct PointerBase_void
|
||||
// implementation for pointer-to-void specializations
|
||||
template<typename T>
|
||||
struct PointerBase_void : NullablePointer<T*>
|
||||
{
|
||||
typedef T element_type;
|
||||
|
||||
|
@ -671,25 +716,24 @@ namespace __gnu_test
|
|||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
|
||||
T* value;
|
||||
using NullablePointer<T*>::NullablePointer;
|
||||
|
||||
explicit PointerBase_void(T* p = nullptr) : value(p) { }
|
||||
T* operator->() const { return this->value; }
|
||||
|
||||
template<typename D, typename U,
|
||||
typename = decltype(static_cast<T*>(std::declval<U*>()))>
|
||||
PointerBase_void(const PointerBase<D, U>& p) : value(p.value) { }
|
||||
|
||||
explicit operator bool() const { return value != nullptr; }
|
||||
PointerBase_void(const PointerBase<D, U>& p)
|
||||
: NullablePointer<T*>(p.operator->()) { }
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
template<typename Derived>
|
||||
struct PointerBase<Derived, void> : PointerBase_void<void>
|
||||
{
|
||||
using PointerBase_void::PointerBase_void;
|
||||
typedef Derived pointer;
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
template<typename Derived>
|
||||
struct PointerBase<Derived, const void> : PointerBase_void<const void>
|
||||
{
|
||||
using PointerBase_void::PointerBase_void;
|
||||
|
|
Loading…
Reference in New Issue