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:
Jonathan Wakely 2019-05-14 12:17:23 +01:00 committed by Jonathan Wakely
parent e25f488d60
commit 066f9ea279
6 changed files with 111 additions and 56 deletions

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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);
}
};

View File

@ -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;

View File

@ -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;